The MASM Forum

General => The Campus => Topic started by: Landsfiskalen on January 16, 2015, 09:35:20 PM

Title: Button refusing to be disabled
Post by: Landsfiskalen on January 16, 2015, 09:35:20 PM
Ok, I set up a procedure to disable the controls I want. But there's a weird problem, one of the buttons refuse to be disabled.


EnableCtrls proc dwEnabledOrDisable:DWORD
invoke EnableWindow,hUnpackButton,dwEnabledOrDisable ; <---------------------- This one refuses to be disabled.
invoke EnableWindow,hPackButton,dwEnabledOrDisable
invoke EnableWindow,hBackupCheckbox,dwEnabledOrDisable
invoke EnableWindow,hBrowseButton,dwEnabledOrDisable
invoke EnableWindow,hProfileComboBox,dwEnabledOrDisable
invoke UpdateWindow,hWindow
ret
EnableCtrls endp


Anyone have ANY idea why this might happen?
Title: Re: Button refusing to be disabled
Post by: vogelsang on January 16, 2015, 10:08:04 PM
Try to update it with UpdateWindow.

hth.
Title: Re: Button refusing to be disabled
Post by: Landsfiskalen on January 16, 2015, 10:37:55 PM
Hi!
I do an UpdateWindow at the end of that proc, on the main window. Should I do one on the specific button perhaps? Cheers!

Quote from: vogelsang on January 16, 2015, 10:08:04 PM
Try to update it with UpdateWindow.

hth.
Title: Re: Button refusing to be disabled
Post by: vogelsang on January 16, 2015, 10:48:21 PM
I see that you updating hWindow - main window as you say. Try to update hUnpackButton and see what will happen.
And what exactly means "refusing". According to MSDN EnableWindow returns:
Quote
Return value

Type: BOOL

If the window was previously disabled, the return value is nonzero.

If the window was not previously disabled, the return value is zero.

I guess it doesn't changed its state to other?

Maybe this helps:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646291%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms646291%28v=vs.85%29.aspx)
Title: Re: Button refusing to be disabled
Post by: hutch-- on January 16, 2015, 11:13:46 PM
Get a handle for each control, then use EnableWindow().
Title: Re: Button refusing to be disabled
Post by: dedndave on January 17, 2015, 12:00:41 AM
perhaps the control has keyboard focus
if it's stubborn, try removing focus and also try de-activating it

http://blogs.msdn.com/b/oldnewthing/archive/2004/08/04/208005.aspx (http://blogs.msdn.com/b/oldnewthing/archive/2004/08/04/208005.aspx)

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646311%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms646311%28v=vs.85%29.aspx)

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646312%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms646312%28v=vs.85%29.aspx)

if all else fails, try SetWindowPos with appropriate flags

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633545%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633545%28v=vs.85%29.aspx)

you can use SWP_NOMOVE and SWP_NOSIZE - no need to set the position arguments
flags are OR'ed together, for example...
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE
Title: Re: Button refusing to be disabled
Post by: Landsfiskalen on January 17, 2015, 12:14:22 AM
Quote from: hutch-- on January 16, 2015, 11:13:46 PM
Get a handle for each control, then use EnableWindow().

Hi!
That's what I'm doing, but this one button refuse to gt disabled when I do invoke EnableWindow,hButton,FALSE.  :icon_confused:

I checked the return value, and it is 0, ie. it was not disabled before.

Will see if dedndave:s input might help.

Cheers!
Title: Re: Button refusing to be disabled
Post by: fearless on January 17, 2015, 02:19:46 AM
Might be handy to see the code where you assign the handle hUnpackButton - just to make sure there arent any typos or maybe a wrong const value used for IDC_UNPACKBUTTON or whatever its named in your resources.
Title: Re: Button refusing to be disabled
Post by: jj2007 on January 17, 2015, 02:33:09 AM
If after two nights of bugchasing you still haven't found it, here is a top secret information for you:
QuoteTo get extended error information, call GetLastError.
Title: Re: Button refusing to be disabled
Post by: ragdog on January 17, 2015, 07:35:37 PM
Hello

I use this in my code to enable or disable many Controls

invoke   EnableControl,hWnd,1001,TRUE

or

invoke   EnableControl,hWnd,1001,FALSE


EnableControl proc uses ebx hWnd:HWND,_ID:DWORD,_bool:BYTE
invoke GetDlgItem,hWnd,_ID
mov ebx,eax
invoke EnableWindow,ebx,_bool
ret
EnableControl endp


Greets,
Title: Re: Button refusing to be disabled
Post by: Landsfiskalen on January 19, 2015, 07:27:52 PM
Hi!
I don't user resources, I create them using CreateWindowsEx. Looks like this:


invoke CreateWindowEx,0,ADDR ButtonClass,ADDR szPackButton,WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_DISABLED,350,169,75,24,hWindow,NULL,hInst,NULL
mov hPackButton,eax


Quote from: fearless on January 17, 2015, 02:19:46 AM
Might be handy to see the code where you assign the handle hUnpackButton - just to make sure there arent any typos or maybe a wrong const value used for IDC_UNPACKBUTTON or whatever its named in your resources.
Title: Re: Button refusing to be disabled
Post by: sinsi on January 19, 2015, 07:50:43 PM
Do you get a valid window handle from CreateWindowEx?
Title: Re: Button refusing to be disabled
Post by: Landsfiskalen on January 19, 2015, 08:51:35 PM
Hi!
Yes, I get a valid windows handle. But it looks like the EnableCtrls procedure is called twice. So I think there's something wrong in my main WindowProc.

Right now I do:


.elseif uMsg == WM_COMMAND
        .if eax == hPackButton
...


But I seem to recall dedndave telling me once that I should use wParam and check the hi and lo word. So looking in to that.

Quote from: sinsi on January 19, 2015, 07:50:43 PM
Do you get a valid window handle from CreateWindowEx?
Title: Re: Button refusing to be disabled
Post by: Landsfiskalen on January 19, 2015, 08:55:22 PM
Ok, so now I got this:


.elseif uMsg == WM_COMMAND
mov edx,[wParam]
movzx eax,dx
shr edx,16
.if edx == BN_CLICKED


So now it should only execute on BN_CLICKED? Do I just put lParam in to eax then and get the handle? What's best practice in this case?
Title: Re: Button refusing to be disabled
Post by: fearless on January 19, 2015, 11:39:56 PM
I use the wNotifyCode mainly for comboboxes and other controls sometimes. You can still specify a control id when creating it using CreateWindowEx - its the third last parameter: hMenu - which can be a control id, like iDC_BtnPack or IDC_BtnUnpack or whatever.

.CONST
IDC_BtnPack EQU 1001
IDC_BtnUnpack EQU 1002

.DATA
ButtonClass db 'button',0
szPackButton db 'Pack',0
szUnpackButton db 'Unpack',0

.DATA?
hUnpackButton dd ?
hPackButton dd ?

.CODE
WndProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    LOCAL wNotifyCode:DWORD

    mov eax, uMsg
    .IF eax==WM_INITDIALOG
        ; do init stuff here, including possibly creating our btn controls here (or somewhere else perhaps, assuming we have hInstance already stored)
        invoke CreateWindowEx,0,ADDR ButtonClass,ADDR szPackButton,WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_DISABLED,350,169,75,24,hWin,IDC_BtnPack,hInstance,NULL
        mov hPackButton,eax
        invoke CreateWindowEx,0,ADDR ButtonClass,ADDR szUnpackButton,WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_DISABLED,350,169,75,24,hWin,IDC_BtnUnpack,hInstance,NULL
        mov hUnpackButton,eax


    .ELSEIF eax == WM_COMMAND
        mov eax, wParam
        shr eax, 16
        mov wNotifyCode, eax
        mov    eax,wParam
        and    eax,0FFFFh
        .IF eax==IDC_BtnUnpack
                ; do something here

        .ELSEIF eax==IDC_BtnPack
                ; do something else here

        .ELSEIF eax==IDC_SomeOtherControl
                ; maybe we check to enable disable controls here, like if user has succesfully opened a file - allow unpack button?

        .ENDIF
         
        ; other code here onwards
       
Title: Re: Button refusing to be disabled
Post by: Landsfiskalen on January 20, 2015, 12:18:35 AM
Changed my code to use constants for the win-controls. Still no go though.  :( The Unpack-button still refuse to be disabled. If I put in a MessageBox call I can see ALL the buttons greyed out. So feels like an update problem? But I do a call to invoke UpdateWindow,hWindow, so should work.  :dazzled:

Quote from: fearless on January 19, 2015, 11:39:56 PM
I use the wNotifyCode mainly for comboboxes and other controls sometimes. You can still specify a control id when creating it using CreateWindowEx - its the third last parameter: hMenu - which can be a control id, like iDC_BtnPack or IDC_BtnUnpack or whatever.

.CONST
IDC_BtnPack EQU 1001
IDC_BtnUnpack EQU 1002

.DATA
ButtonClass db 'button',0
szPackButton db 'Pack',0
szUnpackButton db 'Unpack',0

.DATA?
hUnpackButton dd ?
hPackButton dd ?

.CODE
WndProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    LOCAL wNotifyCode:DWORD

    mov eax, uMsg
    .IF eax==WM_INITDIALOG
        ; do init stuff here, including possibly creating our btn controls here (or somewhere else perhaps, assuming we have hInstance already stored)
        invoke CreateWindowEx,0,ADDR ButtonClass,ADDR szPackButton,WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_DISABLED,350,169,75,24,hWin,IDC_BtnPack,hInstance,NULL
        mov hPackButton,eax
        invoke CreateWindowEx,0,ADDR ButtonClass,ADDR szUnpackButton,WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_DISABLED,350,169,75,24,hWin,IDC_BtnUnpack,hInstance,NULL
        mov hUnpackButton,eax


    .ELSEIF eax == WM_COMMAND
        mov eax, wParam
        shr eax, 16
        mov wNotifyCode, eax
        mov    eax,wParam
        and    eax,0FFFFh
        .IF eax==IDC_BtnUnpack
                ; do something here

        .ELSEIF eax==IDC_BtnPack
                ; do something else here

        .ELSEIF eax==IDC_SomeOtherControl
                ; maybe we check to enable disable controls here, like if user has succesfully opened a file - allow unpack button?

        .ENDIF
         
        ; other code here onwards
       

Title: Re: Button refusing to be disabled
Post by: dedndave on January 20, 2015, 02:27:12 AM
as it happens, BN_CLICKED is 0   :biggrin:

so - no need to check it because if the entire dword is the control ID, then it is a BN_CLICKED notification
however, you are checking against the handle value
use the control ID's, instead

http://msdn.microsoft.com/en-us/library/windows/desktop/ms647591%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms647591%28v=vs.85%29.aspx)

notice that, for menu items, the wParam high word is also 0
for controls, the high word is the notification code (BN_CLICKED = 0)
just make sure to use different ID values for controls and menu items

IDC_BUTTON1   EQU 101
IDC_BUTTON2   EQU 102
IDM_MENUITEM1 EQU 103
IDM_MENUITEM2 EQU 104


    mov     eax,uMsg
    .if eax==WM_COMMAND
        mov     edx,wParam
        .if edx==IDC_BUTTON1

        .elseif edx==IDC_BUTTON2

        .elseif edx==IDC_MENUITEM1

        .elseif edx==IDC_MENUITEM2
Title: Re: Button refusing to be disabled
Post by: jj2007 on January 20, 2015, 02:30:22 AM
Quote from: Landsfiskalen on January 20, 2015, 12:18:35 AMBut I do a call to invoke UpdateWindow,hWindow, so should work.  :dazzled:

UpdateWindow is needed only on extremely rare occasions. You would have had a solution to your problem a long time ago if
a) you would do error checking, e.g. with the Masm32 macro LastError$()
b) you would post your complete code.

Guessing around like you currently do is just wasting everybody's time, including your own.
Title: Re: Button refusing to be disabled
Post by: dedndave on January 20, 2015, 02:38:03 AM
Quote from: Landsfiskalen on January 19, 2015, 07:27:52 PM
Hi!
I don't user resources, I create them using CreateWindowsEx. Looks like this:


invoke CreateWindowEx,0,ADDR ButtonClass,ADDR szPackButton,WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_DISABLED,350,169,75,24,hWindow,NULL,hInst,NULL
mov hPackButton,eax

when you use CreateWindowEx, and the class pointer points to a string that defines a system-defined control,
the hMenu argument of CreateWindowEx should be the control ID
(the system class string for buttons is "button",0)

http://msdn.microsoft.com/en-us/library/windows/desktop/ms632680%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632680%28v=vs.85%29.aspx)

IDC_BUTTON1   EQU 101

        invoke  CreateWindowEx,0,ADDR ButtonClass,ADDR szPackButton,
                WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_DISABLED,
                350,169,75,24,hWindow,IDC_BUTTON1,hInst,NULL


now, you can use WM_COMMAND wParam to check the control ID number   :t
Title: Re: Button refusing to be disabled
Post by: Landsfiskalen on January 20, 2015, 02:42:35 AM
Hi!
I've made those changes, so I have equates for all controls. Still no go. :( Here's the code if anyone have any ideas.

Quote from: dedndave on January 20, 2015, 02:38:03 AM
Quote from: Landsfiskalen on January 19, 2015, 07:27:52 PM
Hi!
I don't user resources, I create them using CreateWindowsEx. Looks like this:


invoke CreateWindowEx,0,ADDR ButtonClass,ADDR szPackButton,WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_DISABLED,350,169,75,24,hWindow,NULL,hInst,NULL
mov hPackButton,eax

when you use CreateWindowEx, and the class pointer points to a string that defines a system control,
the hMenu argument of CreateWindowEx should be the control ID
(the system class string for buttons is "button",0)

http://msdn.microsoft.com/en-us/library/windows/desktop/ms632680%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632680%28v=vs.85%29.aspx)

        invoke  CreateWindowEx,0,ADDR ButtonClass,ADDR szPackButton,
                WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_DISABLED,
                350,169,75,24,hWindow,IDC_BUTTON1,hInst,NULL


now, you can use WM_COMMAND wParam to check the control ID number   :t
Title: Re: Button refusing to be disabled
Post by: dedndave on January 20, 2015, 02:48:45 AM
first - no need to open a ".const" section for EQUates
won't hurt anything, but EQUates are simply assemble-time constants
they don't create any run-time data

your code looks better,
however, ALL system-defined controls should have an ID
this includes edit controls and static controls (used as labels in your program)
Title: Re: Button refusing to be disabled
Post by: dedndave on January 20, 2015, 05:56:38 AM
i want to clarify....

in fact, any child window (which includes controls) should probably have an ID assigned
i have seen people use 0 as an ID number, but i wouldn't do that   :P

so, the hMenu argument for CreateWindowEx....
for top-level windows, either 0 or a menu handle
for child-level windows, a unique control ID number from 1 to 65535

there is actually no rule that says they have to be unique, but it will make more sense if they are   :t
if you run out of numbers, you have too many controls - lol
Title: Re: Button refusing to be disabled
Post by: jj2007 on January 20, 2015, 06:59:35 AM
Quote from: Landsfiskalen on January 20, 2015, 02:42:35 AMStill no go. :( Here's the code if anyone have any ideas.

The unpack button gets disabled or enabled, at least on my Win7-64, and I see no reason why it shouldn't. Try this:

      .if wNotifyCode == BN_CLICKED
                  .if eax == IDC_BUTTON_BROWSE
            if 1
                  .data?
                  toggle dd ?
                  .code
                  not toggle
                  invoke EnableWindow,hUnpackButton, toggle
                  invoke EnableWindow,hPackButton, toggle
            else
                  mov ofn.lStructSize,SIZEOF ofn
                  push hWnd
                  pop ofn.hwndOwner
                  push hInstance
                  pop ofn.hInstance
                  mov ofn.lpstrFilter, OFFSET szFilterString
                  mov ofn.lpstrFile, OFFSET buffer
                  mov ofn.nMaxFile,MAXSIZE
                  mov ofn.Flags, OFN_FILEMUSTEXIST or \
                  OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
                  OFN_EXPLORER or OFN_HIDEREADONLY
                  mov ofn.lpstrTitle, OFFSET szOpenFileTitle
                  invoke GetOpenFileName, ADDR ofn
                  .if eax==TRUE
                        invoke SendMessage,hInputEdit,WM_SETTEXT,0,ADDR buffer
                        invoke EnableWindow,hPackButton,TRUE
                        invoke EnableWindow,hUnpackButton,TRUE
                  .endif
            endif     
Title: Re: Button refusing to be disabled
Post by: dedndave on January 21, 2015, 02:33:53 AM
ok - had a little time to spend on this
cleaned up the code a bit
i also create all the controls in a PROC, and call it from WM_CREATE (and added ID's for all controls)

i think a big problem was the use of tabs - and improper indentation in WndProc
i am a bit OCD about tabs   :lol:
getting the indents to align helped me find an .endif that was out of place

       ;     .endif             this one was a mistake, removed   <------------------

            .elseif eax==IDC_COMBOBOX_PROFILE
                ;IDC_COMBOBOX_PROFILE code

            .endif  ;end of IDC tests
        .endif      ;end of BN_CLICKED - added this one   <------------------


i also modified the structure of WndProc so each WM_ message may return seperate values in EAX

there are 2 places where...
        .if eax==0
            .break
        .endif


should be replaced with...
        .break .if (!eax)

i'll let you decide on that one

i also try to avoid using locals in WndProc and WinMain (especially WndProc)
that's another discussion   :P
Title: Re: Button refusing to be disabled
Post by: Landsfiskalen on January 23, 2015, 04:57:15 AM
Wow! Thanks alot! Will have a proper look at this during the weekend. Thanks again! :)

Quote from: dedndave on January 21, 2015, 02:33:53 AM
ok - had a little time to spend on this
cleaned up the code a bit
i also create all the controls in a PROC, and call it from WM_CREATE (and added ID's for all controls)

i think a big problem was the use of tabs - and improper indentation in WndProc
i am a bit OCD about tabs   :lol:
getting the indents to align helped me find an .endif that was out of place

       ;     .endif             this one was a mistake, removed   <------------------

            .elseif eax==IDC_COMBOBOX_PROFILE
                ;IDC_COMBOBOX_PROFILE code

            .endif  ;end of IDC tests
        .endif      ;end of BN_CLICKED - added this one   <------------------


i also modified the structure of WndProc so each WM_ message may return seperate values in EAX

there are 2 places where...
        .if eax==0
            .break
        .endif


should be replaced with...
        .break .if (!eax)

i'll let you decide on that one

i also try to avoid using locals in WndProc and WinMain (especially WndProc)
that's another discussion   :P