Hi
I m working with modal dialog boxes, and
I found this 2 values in WINDOWS.INC:
WS_TABSTOP equ 10000h
WS_MAXIMIZEBOX equ 10000h
And then when i use the style WS_TABSTOP the dialog box has
a maximization button which i dont want.
Are that 2 values correct ? WS_TABSTOP = 10000h ?
Thanks
Rui
They are correct. WS_TABSTOP is meant for controls, not for the dialog itself, so for Windows there is no ambiguity: You asked for a maximze box, and you got it ;-)
Rui,
I think you are asking why they both have the same values and is this a contradiction? The answer is no. The WS_MAXIMIZE is used by a dialog and the WS_TABSTOP is used by a control within the dialog so there is no problem.
If you do not want the WS_MAXIMIZE, use NOT WS_MAXIMIZE or just remove it from the list.
You can use something like the following to have no Maximize or Minimize boxes:
IDD_DLG1 DIALOGEX 0,0,190,219
CAPTION "ASCII Chart"
FONT 8,"MS Sans Serif",0,0,0
STYLE WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU|DS_CENTER|DS_MODALFRAME
MENU IDM_MNU
BEGIN
CONTROL "7-Bit ASCII Cponversion Chart:",1001,"Static",0x50000000,10,5,105,10,0x00000000
CONTROL "", IDC_LIST1, "SysListView32", LVS_REPORT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP,8,16,174,194,WS_EX_CLIENTEDGE
END
Code taken from the ASCIITable program. Notice the listview has WS_TABSTOP and it does not add a maximize box to the dialog.
-- Paul
[attachment deleted by admin]
Hi all
jj2007,
OK, i understood. Thanks for the reply
Paul,
Thank you. Your example is cool.
Now, i have 1 problem to solve:
How to change the color of a static control ( LTEXT );
I attathed a prog. example: Dialog3.asm and Dialog3.exe in Dialo3.zip and rsrc.zip.
The problem is this: the background color of the names "Name" and "Address" in
the dialog box should be the same as the background color of the window. But i couldnt set it.
It gives me white. There are something that im not understanding well
Can anyone help me
Thanks
Rui
[attachment deleted by admin]
There is more than one way to control the background color of a static control. This code returns a NULL_BRUSH in the WM_CTLCOLORSTATIC handler, which tells GDI not to modify the background. An alternative would be to return a brush of a color that matches the window background, and I think there are probably other ways to do it.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
hInstance dd 0
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
DlgProc proc hDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
SWITCH uMsg
CASE WM_CTLCOLORDLG
invoke GetStockObject, WHITE_BRUSH
ret ; return the brush
CASE WM_CTLCOLORSTATIC
invoke SetTextColor, wParam, 0ff0000h
invoke GetStockObject, NULL_BRUSH
ret ; return the brush
CASE WM_CLOSE
invoke EndDialog,hDlg,0
ENDSW
xor eax, eax
ret
DlgProc endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
invoke GetModuleHandle, NULL
mov hInstance, eax
Dialog "Test", \
"MS Sans Serif",10, \
WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \
1,0,0,120,90,1024
DlgStatic "HELLO WORLD",SS_LEFT,32,35,52,10,100
CallModalDialog hInstance,0,DlgProc,NULL
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Ruyi,
Michael's way is a way that I often use, especially for hyperlinks. But, the easiest way to do it is use an edit controol instead and set the ES_READONLY style. For some reason, that style accomplishes exactly what you want. You can set for no borders, etc, also.
-- Paul
Hi Michael,
Thank you for your help and code. I ran it i saw what it does.
But it doesnt solve the problem because the background is white and pushbuttons
are green as the original color of the window . See it in Dialog4.zip. I want a green
background color for the window. Thats the problem too.
In any case, thanks :U
Hi Paul,
Thanks for your help, too. I go to test your sugestion.
Rui
EDIT: the rsrc file is in the previous post
[attachment deleted by admin]
Rui,
Try using a green brush when you register the class.
invoke CreateSolidBrush,65280 ; 0x00bbggrr
mov wc.hbrBackground,eax
RotateRight,
It doesnt work. We dont register the class because it is a commom control.
I found this in Platform SDK -> User interface services -> windows controls -> Common controls
Common Control Messages
------------------------------------
«When a change is made to the system color settings, Windows sends a
WM_SYSCOLORCHANGE message to all top-level windows.
Your top-level window must forward the WM_SYSCOLORCHANGE message
to its common controls;
otherwise, the controls will not be notified of the color change.
Forwarding the message ensures that the colors used by your common controls
are consistent with those used by other user interface objects.
For example, a toolbar control uses the "3D Objects" color to draw its buttons.
If the user changes the 3D Objects color but the WM_SYSCOLORCHANGE message is not
forwarded to the toolbar, the toolbar buttons will remain in their original color
(or even change to a combination of old and new colors) while the color of other buttons
in the system changes.»
But i dont understand how it works.
Rui
You can always subclass the control and catch the background draw message, see this post (http://www.masm32.com/board/index.php?topic=9591.msg69941#msg69941) for the basics.
Rui,
If you do not have any controls or graphics, etc. beneath the control that has the wrong color, just use the WS_EX_TRANSPARENT style and the color of the background under the control will show through. How about that? Remember to put it in the exStyle part.
-- Paul
Rui,
What colors do you want the dialog and the controls in it to have? I cannot tell from your code what you are trying to do. If you just want the normal dialog colors, there is no need to handle the WM_CTLCOLORDLG or WM_CTLCOLORSTATIC messages.
Also, your code as posted has errors that will keep it from running, at least under Windows 2000. For the main window, the call to RegisterClassEx is failing because your code does not initialize all the members of the WNDCLASSEX structure, and because the structure is LOCAL it initially contains garbage (under Windows 2000 and I think earlier versions). This problem can be corrected by setting all the members of the structure to zero at the start of the procedure:
invoke RtlZeroMemory, ADDR wc, sizeof WNDCLASSEX
Quote from: MichaelW on August 14, 2008, 03:57:53 AMbecause the structure is LOCAL it initially contains garbage (under Windows 2000 and I think earlier versions). This problem can be corrected by setting all the members of the structure to zero at the start of the procedure:
invoke RtlZeroMemory, ADDR wc, sizeof WNDCLASSEX
Under all Windows versions indeed, afaik. It would surprise me if Vista allocated a clean fresh stack to all programs - the prologue macro at least does not do the job for us ;-)
Michael,
Thanks for the reply.
1. About problems on running Windows 2000. I tested it on my XP and it
is to run on XP (only). But you have reason, people with 2000 may not run that
example posted in the forum
2. Usually i dont like to define data in .data? segment (i use only .data) and
all local variables start with some initial value. I forgot it in that
example in WNDCLASSEX struc. To correct it (to fix the bug) we need only to do
mov wc.hIcon, NULL
all other variables have an initial value
3. The prog i posted is to show the problem about how to change the foreground
and text colors in a modal dialog box. Thats the problem.
How to do it when i want text color = Blue and window background= Green
or
when i want text color = Red and window bkg = default colour bkg
etc.
By default, on my XP the dialog wnd has a greenish bkg color and all
other control colors are black (text color is black).
i want to change text color ( SetTextColor ) to another color.
For example
to the color i get with (invoke GetSysColor, COLOR_BACKGROUND = Blue is
what i see). But When i use SetTextColor to BLUE the backgroung of the
text is white and the window backgrond is greenish. If i use
SetBkColor to the color i get from GetSysColor, COLOR_WINDOW it
does nothing.
4. Where i saw information
Platform SDK -> Development Guides -> Windows API -> Functions by category
Control-Color Messages
«
Controls and the system can send control-color messages when they want
the dialog box procedure to paint the background of a control
or other window
by using a specific brush and colors.
This can be useful when applications override the default colors
used in dialog boxes and their controls.
Following are the control-color messages,
which have replaced the WM_CTLCOLOR message.
WM_CTLCOLORBTN
WM_CTLCOLORDLG
WM_CTLCOLOREDIT
WM_CTLCOLORLISTBOX
WM_CTLCOLORSCROLLBAR
WM_CTLCOLORSTATIC
A control sends a control-color message to the dialog box procedure just before
it paints its own background.
The message allows the procedure to specify which brush to use and
to set the background and foreground colors.
The procedure specifies a brush by returning the brush handle.
To set the background and foreground colors,
the procedure uses the SetBkColor and SetTextColor functions with
the control's display device context.
The control-color message passes a handle to the display device context
to the procedure in the message's wParam parameter
...
In any case, when a dialog box procedure does not process a control-color message,
the system uses a brush with the default window color to paint the background
for all controls and windows except scroll bars.
An application can retrieve the default window color by passing the COLOR_WINDOW
value to the GetSysColor function.
While the background is painted, the foreground color for the
display device context is set to the default text color (COLOR_WINDOWTEXT)
»
«
WM_CTLCOLORSTATIC Notification
A static control, or an edit control that is read-only or disabled,
sends the WM_CTLCOLORSTATIC message to its parent window when the control
is about to be drawn.
By responding to this message, the parent window can use
the specified device context handle
to set the text and background colors of the static control.
A window receives this message through its WindowProc function.
WM_CTLCOLORSTATIC
WPARAM wParam
LPARAM lParam;
wParam = Handle to the device context for the static control window.
lParam = Handle to the static control.
Return Value: If an application processes this message,
the return value is a handle to a brush that the system uses
to paint the background of the static control.
»
;...................................
Michael,
It seems to be easy.
I tried to use this information. But i am doing something wrong
or i misunderstood something ...and, at last, it doesnt work
Rui
Microsoft could have done a better job on the WM_CTLCOLORSTATIC documentation, and it should have included a working example.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
hInstance dd 0
hBrush dd 0
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
DlgProc proc hDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
SWITCH uMsg
CASE WM_INITDIALOG
invoke CreateSolidBrush, 0ff00h
mov hBrush, eax
CASE WM_CTLCOLORDLG
;------------------------------------------
; Comment this out for default background.
;------------------------------------------
return hBrush
CASE WM_CTLCOLORSTATIC
;----------------------------------------------
; The default message handling will ignore the
; text color setting if no brush is returned.
;----------------------------------------------
;--------------------------------
; Blue text on green background.
;--------------------------------
invoke SetTextColor, wParam, 0ff0000h
invoke SetBkColor, wParam, 0ff00h
invoke GetStockObject, NULL_BRUSH
ret
;invoke SetTextColor, wParam, 0ff0000h
;invoke SetBkMode, wParam, TRANSPARENT
;return hBrush
;invoke SetTextColor, wParam, 0ff0000h
;invoke SetBkMode, wParam, TRANSPARENT
;invoke GetStockObject, NULL_BRUSH
;ret
;---------------------------------
; Red text on default background.
;---------------------------------
;invoke SetTextColor, wParam, 0ffh
;invoke SetBkMode, wParam, TRANSPARENT
;invoke GetStockObject, NULL_BRUSH
;ret
CASE WM_CLOSE
invoke DeleteObject, hBrush
invoke EndDialog,hDlg,0
ENDSW
xor eax, eax
ret
DlgProc endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
invoke GetModuleHandle, NULL
mov hInstance, eax
Dialog "Test", \
"MS Sans Serif",10, \
WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \
1,0,0,120,90,1024
DlgStatic "HELLO WORLD",SS_LEFT,32,35,52,10,100
CallModalDialog hInstance,0,DlgProc,NULL
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Also, are you aware that I posted an example that displays a list of the system colors here (http://www.masm32.com/board/index.php?topic=8284.msg60356#msg60356).
Michael,
many Thanks for your HELP.
Something failed when i want to set the backgroud window to green.
It gives me «Blue text on green background. -> green UNDER THE TEXT !!!»
See my file Dialog5_1 ( last proc DlgProc1)
But it works when i use default background (this is what i want first).
This solve my problem
Its in the file Dialog5_2
About documentation, it is good but seems to have some BUGS;
«Microsoft could have done a better job on the WM_CTLCOLORSTATIC documentation,
and it should have included a working example.». I say the same
note: The file rsrc.rc is elsewhere behind
Thanks for the code
Rui
PS:
«are you aware that I posted an example that displays a list of the system colors»
Sorry Michael, i was sleeping ! I downloaded it now and saw it. Nice work. Thanks.
EDIT:
Paul,
WS_EX_TRANSPARENT doesnt work with EDITTEXT control. Thanks
Rui
[attachment deleted by admin]
Quote from: jj2007 on August 13, 2008, 09:21:51 PM
You can always subclass the control and catch the background draw message.
Hi jj2007,
I tried to studied subclass today. I did an example but it didnt run well ! I think i need
a good and simple example to understand what is subclassing, what it does.
Where to put SetWindowLong ? Catching the background message could be a good example.
Rui
Quote from: RuiLoureiro on August 15, 2008, 06:14:07 PM
I think i need a good and simple example to understand what is subclassing, what it does.
It is really simple: You can catch all the "internal" messages of the control, and react to them. Here is a skeleton for an edit control. Instead of returning 0, you can return specific values, e.g. a brush. Sorry I am too tired right now to elaborate more on this, but MSDN has all these messages somewhere.
invoke SetWindowLong, hEdit, ; use just behind the line
GWL_WNDPROC, SubEdit ; where you create your control
mov opEdit, eax ; the old pointer, see below
SubEdit PROTO:DWORD,:DWORD,:DWORD,:DWORD ; move to proto section
opEdit dd ? ; move to data? section
SubEdit proc hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
SWITCH uMsg
CASE WM_KEYDOWN
return 0
CASE WM_CHAR
return 0
CASE WM_KEYUP
return 0
DEFAULT
xor eax, eax
ENDSW
invoke CallWindowProc, opEdit, hwnd, uMsg, wParam, lParam
ret
SubEdit endp
Quote from: jj2007 on August 15, 2008, 06:37:37 PM
It is really simple: You can catch all the "internal" messages of the control, and react to them.
Hi jj2007,
I wrote this code below to test the use of SetWindowLong.
Could you comment it, if you dont mind
Thanks
This is the procedure called by a Dialog window:
..................................................................
IDC_Exit = This is the ID of EXIT BUTTON
_hIDC_Exit = This is the EXIT BUTTON's handle
...................................................................
DlgProc proc hWnd:DWORD, iMsg:DWORD, wParam:DWORD, lParam:DWORD
mov eax, hWnd
mov _hDlgWnd, eax ; This is the Dialog window's handle
.if iMsg==WM_INITDIALOG
; ------------------------------
; Get the handle of EXIT button
; ------------------------------
invoke GetDlgItem, hWnd, IDC_Exit
mov _hIDC_Exit, eax ; This is the EXIT BUTTON's handle
;###########################################################
;**** ExitProc is the NEW processor to the EXIT button ****
; **********************************************************
invoke SetWindowLong, eax, GWL_WNDPROC, offset ExitProc
mov _hSubDlg, eax
;###########################################################
etc.
So, after
invoke SetWindowLong, eax, GWL_WNDPROC, offset ExitProc
all messages to the EXIT button are processed by ExitProc, no ?
They are NOT processed inside DlgProc. No or can be ?
This is the ExitProc:
ExitProc proc hWnd:DWORD, iMsg:DWORD, wParam:DWORD, lParam:DWORD
.if iMsg==WM_COMMAND
mov eax, wParam
mov edx,eax
shr edx,16
.if edx == BN_CLICKED
.if eax==IDC_Exit ; <- This is the ID of EXIT BUTTON
;
;invoke SendMessage, hWnd, WM_CLOSE, NULL, NULL
invoke SendMessage, _hDlgWnd, WM_CLOSE, NULL, NULL
mov eax, TRUE
ret
.endif
.endif
.endif
;
; not processed HERE
; ******************
invoke CallWindowProc, _hSubDlg, hWnd, iMsg, wParam, lParam
ret
ExitProc endp
The only thing i want to do inside ExitProc is to close the Dialog window
if i click at the EXIT button.
Whats is wrong ?
Thank you
Rui
You don't explain well what your problem is, and I don't see in your code any message boxes that indicate you are actually debugging your code - so I am just guessing now: It might be that you need to use DWL_DLGPROC instead of GWL_WNDPROC. Quote from MSDN (http://msdn.microsoft.com/en-us/library/ms633591(VS.85).aspx):
The following values are also available when the hWnd parameter identifies a dialog box.
DWL_DLGPROC
Sets the new address of the dialog box procedure.
If you want to know what's going on, just test it with both variants, and see if you can catch any messages, e.g WM_PAINT. With the latter, it is highly recommended to use this macro:
.data
ShowMSG dd IDOK
deb MACRO arg ; deb "Wow, I got a WM_PAINT!"
pushad
.if ShowMSG==IDOK
mov ShowMSG, IDCANCEL ; prevent multiple boxes
invoke MessageBox, hWnd, chr$(<arg>), addr DebugMsg, MB_OKCANCEL
mov ShowMSG, eax
.endif
popad
ENDM
Once you click Cancel, you will no longer see boxes.
Usage:
.if iMsg==WM_COMMAND
deb "Command"
mov eax, wParam
mov edx,eax
shr edx,16
.if edx == BN_CLICKED
deb "Clicked"
.if eax==IDC_Exit ; <- This is the ID of EXIT BUTTON
deb "exit"
;
jj2007,
Thanks for the reply
Ok, i attached some files Dialog7_1.zip (asm & exe)
Dialog7_2.zip (asm & exe)
rsrc.zip (rsrc.rc)
1. In the example Dialog7_1.asm i used
invoke SetWindowLong, eax, DWL_DLGPROC, offset ExitProc
and inside ExitProc i have:
ExitProc proc hWnd:DWORD, iMsg:DWORD, wParam:DWORD, lParam:DWORD
deb "START ExitProc"
The result is: it never triggers «deb "START ExitProc"».
OK, hWnd parameter DOESNT identify a dialog box
BUT an EXIT button
2. Now, comment this ( inside Dialog7_1.asm )
; invoke SetWindowLong, eax, DWL_DLGPROC, offset ExitProc
uncomment this
invoke SetWindowLong, eax, GWL_WNDPROC, offset ExitProc
compile, run, Click on Open Dialog (in the menu)
[to work, i am using Hutch Quick Editor ]
i get --> "START ExitProc"
OK, hWnd parameter identifies the EXIT button
and NOW it goes to ExitProc
3. In the example Dialog7_2.asm i used
invoke SetWindowLong, eax, GWL_WNDPROC, offset ExitProc
;deb "START ExitProc"
4. Run, Click on Open Dialog (in the menu)
Click on Exit button
i get --> "EXIT inside DlgProc"
and NOT "EXIT inside ExitProc". Thats the question.
Why isnt it processed by ExitProc ?
There is something i dont understand well
about SetWindowLong !
Thats all for now
Thanks
Rui
[attachment deleted by admin]
It's GWL_WNDPROC, not the DLG variant. The button does not get many messages, but try yourself:
.elseif iMsg==WM_KEYDOWN ; confirm with space
deb "Msg KEYDOWN"
.elseif iMsg==WM_NOTIFY ; never seen
deb "Msg NOTIFY"
.elseif iMsg==BM_SETSTATE ; that's your's, Rui!
deb "Msg BM_SETSTATE"
;.elseif iMsg==WM_PAINT
Rui, I suppose you know the MSDN docu on button messages? Especially the section Notification Messages from Buttons (http://msdn.microsoft.com/en-us/library/bb775941(VS.85).aspx) is interesting.
Quote from: jj2007 on August 17, 2008, 03:14:29 PM
Rui, I suppose you know the MSDN docu on button messages? Especially Notification Messages from Buttons
jj2007,
not much about controls. I am reading that docs and doing some exercises now.
It seems i am understanding what SetWindowLong does.
Do you know ControlSpy ?
Did you see WS_TABSTOP2 post ? Have any idea about the problem ?
Thank you jj2007
Rui
Quote from: RuiLoureiro on August 18, 2008, 05:50:26 PM
Quote from: jj2007 on August 17, 2008, 03:14:29 PM
Rui, I suppose you know the MSDN docu on button messages? Especially Notification Messages from Buttons
jj2007,
not much about controls. I am reading that docs and doing some exercises now.
It seems i am understanding what SetWindowLong does.
Subclassing is an essential technique, so that is certainly a good exercise. Maybe this would work, too:
WndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
SWITCH uMsg
CASE WM_COMMAND ; specific WM_COMMAND messages
mov eax, wParam
shr eax, 16 ; shift right to get the HIWORD
mov cMsg, eax ; the WM_COMMAND message
switch cMsg
case LBN_SELCHANGE
deb "Listbox LBN_SELCHANGE"
case BN_CLICKED ; LbChk, BST_
deb "BN_CLICKED"
Quote
Do you know ControlSpy ?
Did you see WS_TABSTOP2 post ? Have any idea about the problem ?
No, but sounds interesting. Will have a look at the WS_TABSTOP2 post asap.
Quote
Thank you jj2007
Rui
My pleasure :thumbu
jj2007,
You gave me the link to MSDN. There, above, we have "Subclassing Controls" and Control Spy 2.0
http://www.microsoft.com/downloads/details.aspx?FamilyID=19d4294d-0531-4ec2-8b27-2e463b315f16&displaylang=en.
I will try your example. When i try an example i need some time to think about the details
involved and it takes a lot of time.
Thank you !
Rui
Quote from: RuiLoureiro on August 18, 2008, 08:54:10 PM
I will try your example.
I used SWITCH/CASE for first level messages and switch/case for messages inside messages. It's a matter of taste.
Thanks for the link!
jj
jj2007,
It seems i solved the problem i had in WS_TABSTOP2 topic.
Your «deb macro» was very useful. Thanks for that !
I did this too,
.data
_DebugMsg db 'Test Window', 0 ; i use _DebugMsg for GLOBAL AND DebugMsg for LOCAL
; inside the same proc i can have both etc.
; This is an example
;....................................................................................
debWnd MACRO arg, hWnd ; use: debWnd "message WM_NOTIFY", hWnd
pushfd
pushad
.if ShowMSG==IDOK
mov ShowMSG, IDCANCEL ; prevent multiple boxes
invoke MessageBox, hWnd, chr$(<arg>), addr _DebugMsg, MB_OKCANCEL
mov ShowMSG, eax
.endif
popad
popfd
ENDM
About SetWindowLong, it extends a default control processor to
one we define, but it seems we never receive WM_COMMAND or
WM_NOTIFY inside the new one (these messges are reported to
the parent window, only - i think - by the default control processor)
About Switch/Case, etc., i used it a long time ago and i know.
1st level: SWITCH
CASE
2nd level: switch
case
...
Rui