The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: dedndave on February 23, 2011, 04:17:35 PM

Title: Prevent Menu Wrap
Post by: dedndave on February 23, 2011, 04:17:35 PM
i would like to prevent the main menu from wrapping
i can easily process WM_GETMINMAXINFO messages to set a minimum window width
and i can empirically find a minimum width of some constant value that works
however, i would like to know what the required width is that will display the menu without wrapping
there must be a way to find the value programmatically so that it works for different themes, menu text sizes, display resolutions, etc
any ideas ??????

(http://www.masm32.com/board/index.php?action=dlattach;topic=16156.0;id=8885)


the attachment is the above PNG image renamed as a ZIP
Title: Re: Prevent Menu Wrap
Post by: dedndave on February 23, 2011, 05:11:19 PM
i guess i can play with MenuItemFromPoint
not very elegant   :P
Title: Re: Prevent Menu Wrap
Post by: qWord on February 23, 2011, 06:07:40 PM
maybe GetMenuBarInfo() (http://msdn.microsoft.com/en-us/library/ms647833(v=VS.85).aspx) does it.
Title: Re: Prevent Menu Wrap
Post by: dedndave on February 23, 2011, 06:18:36 PM
thanks qWord   :U

i had looked at that one and did not see what i wanted, at first (coordinates of the menu bar won't do it)
now i see that i can specify a menu item and get coordinates - that may do the trick
Title: Re: Prevent Menu Wrap
Post by: jj2007 on February 23, 2011, 06:28:25 PM
Put together a "menu titles" string of format File__Edit__Format__Other and estimate its width. Should be precise enough...
Title: Re: Prevent Menu Wrap
Post by: dedndave on February 23, 2011, 06:39:18 PM
not sure i understand what you mean, Jochen
Title: Re: Prevent Menu Wrap
Post by: jj2007 on February 23, 2011, 07:53:40 PM
Concat the menu titles, then use GetTextMetrics and the tmAveCharWidth member of the TEXTMETRIC structure.
Title: Re: Prevent Menu Wrap
Post by: qWord on February 23, 2011, 09:47:12 PM
hi,
here an short example showing how it could be done:
Quoteinclude masm32rt.inc
.686p
.mmx
.xmm

MENUBARINFO struct
    cbSize      DWORD   ?
    rcBar       RECT    <>
    hMenu       HMENU   ?
    hwndMenu    HWND    ?
    flags       SDWORD  ? ; fBarFocused=1 , fFocused=2
    ;fBarFocused : 1
    ;fFocused   : 1
MENUBARINFO ends
PMENUBARINFO typedef ptr MENUBARINFO

.data?
    hInstance   HINSTANCE   ?
    hwnd        HWND        ?
    cxFrame     DWORD       ?
    cxMin       DWORD       ?
.code

WndProc proto hWnd:HWND,uMgs:UINT,wParam:WPARAM,lParam:LPARAM

main proc
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG

    mov hInstance,rv(GetModuleHandle,0)
    mov wc.hInstance,eax
    mov wc.cbSize,SIZEOF wc
    mov wc.style,CS_HREDRAW or CS_VREDRAW or CS_SAVEBITS
    mov wc.lpfnWndProc,OFFSET WndProc
    mov wc.cbClsExtra,0
    mov wc.cbWndExtra,0
    mov wc.hIcon,rv(LoadIcon,0,IDI_APPLICATION)
    mov wc.hIconSm,eax
    mov wc.hCursor,rv(LoadCursor,0,IDC_ARROW)
    mov wc.lpszMenuName,0
    mov wc.hbrBackground,rv(GetStockObject,WHITE_BRUSH);
    mov wc.lpszClassName,chr$("Win32Wnd")
    invoke RegisterClassEx,ADDR wc
   
    mov esi,rv(CreateMenu)
    fn AppendMenu,esi,MF_STRING,1,"entry1"
    fn AppendMenu,esi,MF_STRING,2,"entry2"
    fn AppendMenu,esi,MF_STRING,3,"entry3"
    fn AppendMenu,esi,MF_STRING,4,"entry4"
   
    mov ebx,ASM(mov edi,rv(GetSystemMetrics,SM_CXSCREEN))
    mov ecx,rv(GetSystemMetrics,SM_CYSCREEN)
    shr ebx,1
    shr eax,1
    shr edi,2
    shr ecx,2
    mov esi,rv(CreateWindowEx,0,wc.lpszClassName,"Win32Wnd",WS_VISIBLE or WS_SYSMENU or WS_MAXIMIZEBOX or WS_MINIMIZEBOX or WS_SIZEBOX,edi,ecx,ebx,eax,0,esi,hInstance,0)
    mov hwnd,eax
    invoke UpdateWindow,esi
   
    .while 1
        invoke GetMessage,ADDR msg,0,0,0
        .break .if !eax || eax == -1
        invoke TranslateMessage,ADDR msg
        invoke DispatchMessage,ADDR msg     
    .endw

    invoke ExitProcess,0
   
main endp

WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL rect[2]:RECT
LOCAL mbi:MENUBARINFO

    .if uMsg == WM_CLOSE
        invoke PostQuitMessage,0
    .elseif uMsg == WM_CREATE
        invoke GetClientRect,hWnd,ADDR rect
        invoke GetWindowRect,hWnd,ADDR rect[16]
        mov edx,rect[16].right
        sub edx,rect[16].left
        sub edx,rect.right
        mov cxFrame,edx
        mov mbi.cbSize,SIZEOF mbi
        invoke GetMenuBarInfo,hWnd,OBJID_MENU,4,ADDR mbi    ; coord. are relativ to screen!
        mov eax,mbi.rcBar.right
        sub eax,rect[16].left
        add eax,cxFrame
        mov cxMin,eax   
    .elseif uMsg == WM_GETMINMAXINFO
        mov edx,lParam
        m2m [edx].MINMAXINFO.ptMinTrackSize.x,cxMin
    .else
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .endif
   
    xor eax,eax
    ret
   
WndProc endp
end main
Title: Re: Prevent Menu Wrap
Post by: MichaelW on February 23, 2011, 09:49:23 PM
A different version based on an in-memory dialog:

;==============================================================================
; Build as console app.
;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================

printf MACRO format:REQ, args:VARARG
    IFNB <args>
        invoke crt_printf, cfm$(format), args
    ELSE
        invoke crt_printf, cfm$(format)
    ENDIF
    EXITM <>
ENDM

;==============================================================================

MENUBARINFO STRUCT
    cbSize    DWORD ?
    rcBar     RECT  <>
    hMenu     HMENU ?
    hwndMenu  HWND  ?
    focused   DWORD ?
MENUBARINFO ENDS

;==============================================================================

IDM_FILE equ 100
IDM_EDIT equ 101
IDM_VIEW equ 102
IDM_HELP equ 103

;==============================================================================
    .data
        hMenu     dd 0
        hFileMenu dd 0
        hEditMenu dd 0
        hViewMenu dd 0
        hHelpMenu dd 0
        mbi       MENUBARINFO <SIZEOF MENUBARINFO>
    .code
;==============================================================================

SetClientSize proc uses ebx hwnd:HWND, pixelWidth:DWORD, pixelHeight:DWORD

    LOCAL rcc:RECT, rcw:RECT

    invoke GetClientRect, hwnd, ADDR rcc
    invoke GetWindowRect, hwnd, ADDR rcw

    mov ecx, rcw.right
    sub ecx, rcw.left       ; ecx = window width - 1

    mov eax, pixelWidth
    dec eax                 ; eax = pixelWidth - 1
    mov ebx, rcc.right      ; ebx = client width - 1
    sub ebx, eax            ; ebx = difference
    sub ecx, ebx            ; adjust width

    mov edx, rcw.bottom     ; edx = window height - 1
    sub edx, rcw.top

    mov eax, pixelHeight
    dec eax                 ; eax = pixelHeight - 1
    mov ebx, rcc.bottom     ; ebx = client height - 1
    sub ebx, eax            ; ebx = difference
    sub edx, ebx            ; adjust height

    invoke MoveWindow, hwnd, rcw.left, rcw.top, ecx, edx, TRUE

    ret

SetClientSize endp

;==============================================================================

DlgProc proc hwndDlg:dword, uMsg:dword, wParam:dword, lParam:dword

    LOCAL rc:RECT
    LOCAL pt:POINT

    SWITCH uMsg

      CASE WM_INITDIALOG

          invoke CreateMenu
          mov hMenu, eax
          invoke CreateMenu
          mov hFileMenu, eax
          invoke CreateMenu
          mov hEditMenu, eax
          invoke CreateMenu
          mov hViewMenu, eax
          invoke CreateMenu
          mov hHelpMenu, eax
          invoke AppendMenu, hMenu, MF_POPUP, hFileMenu, chr$("&File")
          invoke AppendMenu, hMenu, MF_POPUP, hEditMenu, chr$("&Edit")
          invoke AppendMenu, hMenu, MF_POPUP, hViewMenu, chr$("&View")
          invoke AppendMenu, hMenu, MF_POPUP, hHelpMenu, chr$("&Help")
          invoke SetMenu, hwndDlg, hMenu

          ;--------------------------------------------------------
          ; Get the menu info for the fourth item on the menu bar.
          ;--------------------------------------------------------

          invoke GetMenuBarInfo, hwndDlg, OBJID_MENU, 4, ADDR mbi
          printf("GetMenuBarInfo: %d\n", eax)

          ;----------------------------------------------------------------
          ; Convert the returned screen coordinates to client coordinates.
          ; The Y coordinate will be discarded.
          ;----------------------------------------------------------------

          printf("mbi.rcBar.right: %d\n", mbi.rcBar.right)
          push mbi.rcBar.right
          pop pt.x
          push 0
          pop pt.y
          invoke ScreenToClient, hwndDlg, ADDR pt
          printf("pt.x: %d\n", pt.x)

          ;----------------------------------------------------------
          ; Get the current client coordinates, need rc.bottom only.
          ;----------------------------------------------------------

          invoke GetClientRect, hwndDlg, ADDR rc
          printf("rc.right: %d\n", rc.right)
          printf("rc.bottom: %d\n", rc.bottom)

          ;------------------------------------
          ; Adjust rc.bottom to client height.
          ;------------------------------------

          inc rc.bottom

          ;----------------------------------------------------
          ; Under Windows 2000 this adjuatment is necessary to
          ; prevent the menu from wrapping.
          ;----------------------------------------------------

          add pt.x, 12
          printf("pt.x+12: %d\n", pt.x)

          ;---------------------------------------------------
          ; Set the new width and leave the height unchanged.
          ;---------------------------------------------------

          invoke SetClientSize, hwndDlg, pt.x, rc.bottom

          ;---------------
          ; Check result.
          ;---------------

          invoke GetClientRect, hwndDlg, ADDR rc
          printf("rc.right after sizing: %d\n", rc.right)
          printf("rc.bottom after sizing: %d\n", rc.bottom)


      CASE WM_COMMAND

          SWITCH wParam

              CASE IDCANCEL

                  invoke EndDialog, hwndDlg, 0

          ENDSW

      CASE WM_CLOSE

        invoke EndDialog, hwndDlg, 0

    ENDSW

    xor eax, eax
    ret

DlgProc endp

;==============================================================================
start:
;==============================================================================

    Dialog "Test", "MS Sans Serif",10, \
           WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \
           0,0,0,120,60,1024

    invoke GetModuleHandle, NULL

    CallModalDialog eax,0,DlgProc,NULL

    exit
;==============================================================================
end start
Title: Re: Prevent Menu Wrap
Post by: dedndave on February 24, 2011, 02:30:33 AM
thanks guys   :U

on qWord's version, i had to add 2 pixels - i will try to figure out why when i get home
Title: Re: Prevent Menu Wrap
Post by: MichaelW on February 24, 2011, 04:48:39 AM
When I was investigating the reason for the 12-pixel pad, using a sizeable window, I determined that the system maintains a minimum 14-pixel space between the right edge of the rightmost menu "button" and the client area border. BTW, the value 12 includes the 1-pixel adjustment from the zero-based rc.right coordinate to the client width, so the minimum pad is actually 11 pixels.
Title: Re: Prevent Menu Wrap
Post by: dedndave on February 24, 2011, 05:49:36 AM
well - i think the border comes into play
qWord's calculation accounts for one border - but not the other
when we set the limit in the MINMAXINFO structure, we want a window size - not a client size
at any rate, to avoid all the messy calculations, i was going to try this:

1) get the right edge of the last menu item
2) subtract that from the left edge of the first menu item
3) use the AdjustWindowRect function to get the minimum window width
4) process WM_GETMINMAXINFO

steps 1-3 are done at init

had a busy day - off to bed for me
i'll play with it tomorrow
Title: Re: Prevent Menu Wrap
Post by: dedndave on February 24, 2011, 05:14:53 PM
well - i got it to work - more or less - lol

first, let's start with the MENUBARINFO structure
MSDN defines it this way:
typedef struct tagMENUBARINFO {
  DWORD cbSize;
  RECT  rcBar;
  HMENU hMenu;
  HWND  hwndMenu;
  BOOL  fBarFocused;
  BOOL  fFocused;
} MENUBARINFO, *PMENUBARINFO;

in the community content...
struct definition not correct
from WinUser.h:
...
BOOL fBarFocused:1; // bar, popup has the focus
BOOL fFocused:1; // item has the focus
...

that probably makes sense, if you are a C programmer - lol
the way i see it, fBarFocused and fFocused are bit-fields
although, i am not sure what the correct name is to assign to the dword
i am going to use fFocus
qWord is close to being right - the values are 1 or 2 - so bits 0 and 1 are the fields
there is probably a correct way to define that using FIELD

next, the GetMenuBarInfo function does indeed return screen coordinates
the documentation uses the term "window coordinates" - a little misleading, i think
if i look at the left edge of the first menu item, it gives you the left edge of the client area
so - no need to call that function twice - i use ScreenToClient instead

now for the pad
if i grab the right coordinate (which is actually the right + 1 in RECT structures),
i can add Michael's magic number of 14 and get working results
however, a more appropriate way to do it is to call AdjustWindowRect
remember - we have client width - we want window width - and, we want to account for differently themed borders
oddly enough, AdjustWindowRect does not like it if you use 0 for the left and top client rectangle
so, adding some constant to all the values makes it work correctly
any constant will work (so long as it is larger than the theme border width), as it gets subtracted out
if you use the menu item rectangle as is, it should always work

so.....
1) INVOKE GetMenuBarInfo,hWnd,OBJID_MENU,4,addr mbi
2) INVOKE ScreenToClient,hWnd,addr mbi.rcBar.right
3) set the left and top to 8, and add 8 to mbi.rcBar.right
4) INVOKE AdjustWindowRect,addr mbi.rcBar,WS_THICKFRAME,TRUE
the function does not allow using WS_OVERLAPPED, so i used a style that is allowed and has the same border
5) subtract the left edge from the right edge
6) add the corrected pad of 8 to obtain the minimum window width
        push    8
        INVOKE  GetMenuBarInfo,hWnd,OBJID_MENU,4,addr mbi
        pop     edi
        INVOKE  ScreenToClient,hWnd,addr mbi.rcBar.right
        mov     mbi.rcBar.left,edi
        mov     mbi.rcBar.top,edi
        add     mbi.rcBar.right,edi
        INVOKE  AdjustWindowRect,addr mbi.rcBar,WS_THICKFRAME,TRUE
        mov     eax,mbi.rcBar.right
        sub     eax,mbi.rcBar.left
        add     eax,edi
        mov     cxMinimum,eax
Title: Re: Prevent Menu Wrap
Post by: MichaelW on February 24, 2011, 10:04:19 PM
I used client coordinates and sized the client area simply because the menu bar needs to fit the client area. Also, for the menu item coordinates to be useable the window must initially be wide enough to prevent the menu from wrapping.
Title: Re: Prevent Menu Wrap
Post by: dedndave on February 24, 2011, 11:31:33 PM
yes - your version is a little different
we are processing the WM_GETMINMAXINFO message to set the minimum window width
the code i posted above is the init code to determine what value to set it to
qWord's WndProc has the message process code - it's very simple
Title: Re: Prevent Menu Wrap
Post by: dedndave on July 29, 2011, 02:56:39 AM
just to update this thread a little - in case anyone uses it as reference...

i was playing with the windows appearance settings - font size
as previously discussed, the "magic number" is 8 for the normal sized menu font
for large font, it is 9
for extra large font, it is 11
now, you can go into SystemParametersInfo, SPI_GETNONCLIENTMETRICS and retrieve the LOGFONT for menu text
(i am guessing the magic number is actually the width of a cell)
however, it is likely to be a mapped font, and you have to take more steps to find cell width
all that is way too much code for this - lol
my choice - i use the method i posted above, only i use a magic number of 12   :bg
;****************************************************************************************

MbMin   PROC

;set minimum window width value
;the resulting value is used in reply to WM_GETMINMAXINFO,
;to set the MINMAXINFO.ptMinTrackSize.x value
;this prevents the menu bar from wrapping
;
;MAIN_MENU_ITEMS = number of items in main menu
;
;MENUBARINFO STRUCT
; cbSize           dd ?
; rcBar            RECT <>
;   left             dd ?
;   top              dd ?
;   right            dd ?
;   bottom           dd ?
; hMenu            dd ?
; hwndMenu         dd ?
; fBarFocused      dw ?
; fFocused         dw ?
;
;POINT STRUCT
; x                dd ?
; y                dd ?

        push    edi
        push    sizeof MENUBARINFO
        pop     edi
        pushad
        INVOKE  GetMenuBarInfo,hWin,OBJID_MENU,MAIN_MENU_ITEMS,esp
        add     esp,12
        INVOKE  ScreenToClient,hWin,esp
        pop     ecx                                      ;x
        pop     edx                                      ;y
        add     ecx,edi
        add     edx,edi
        push    edx                                      ;bottom
        push    ecx                                      ;right
        push    edi                                      ;top
        push    edi                                      ;left
        mov     eax,esp
        INVOKE  AdjustWindowRect,eax,WS_THICKFRAME,TRUE
        pop     edx                                      ;left
        pop     ecx                                      ;top
        pop     eax                                      ;right
        sub     eax,edx
        add     eax,12                                   ;magic number
        add     esp,16
        mov     MinWidth,eax
        pop     edi
        ret

MbMin   ENDP

;****************************************************************************************

Title: Re: Prevent Menu Wrap
Post by: dedndave on July 29, 2011, 03:40:31 AM
here it is in "bloat mode"   :bg
for those who do not like my push/pops
;****************************************************************************************

MbMin   PROC    USES EDI

;set minimum window width value
;the resulting value is used in reply to WM_GETMINMAXINFO,
;to set the MINMAXINFO.ptMinTrackSize.x value
;this prevents the menu bar from wrapping
;
;MAIN_MENU_ITEMS = number of items in main menu
;
;MENUBARINFO STRUCT
; cbSize           dd ?
; rcBar            RECT <>
;   left             dd ?
;   top              dd ?
;   right            dd ?
;   bottom           dd ?
; hMenu            dd ?
; hwndMenu         dd ?
; fBarFocused      dw ?
; fFocused         dw ?

        LOCAL   mbi:MENUBARINFO

        mov     edi,sizeof MENUBARINFO
        mov     mbi.cbSize,edi
        INVOKE  GetMenuBarInfo,hWin,OBJID_MENU,MAIN_MENU_ITEMS,addr mbi
        INVOKE  ScreenToClient,hWin,addr mbi.rcBar.right
        mov     mbi.rcBar.left,edi
        add     mbi.rcBar.right,edi
        mov     mbi.rcBar.top,edi
        add     mbi.rcBar.bottom,edi
        INVOKE  AdjustWindowRect,addr mbi.rcBar,WS_THICKFRAME,TRUE
        mov     eax,mbi.rcBar.right
        sub     eax,mbi.rcBar.left
        add     eax,12                                              ;magic number
        mov     MinWidth,eax
        ret

MbMin   ENDP

;****************************************************************************************
Title: Re: Prevent Menu Wrap
Post by: dedndave on July 30, 2011, 03:11:02 PM
still playing with this   :bg

i wrote some code to see what rectangle values are returned at different times
i got some very interesting results...
minimized, during WM_CREATE: (application started with minimized window)

    window rect: 176 232 877 627
menu bar "File": 180 262 208 281

--------------------------

maximized, during WM_CREATE: (application started with maximized window)

    window rect: 176 232 877 627
menu bar "File": 180 262 208 281

--------------------------

minimized:

    window rect: -32000 -32000 -31840 -31969
menu bar "File": -31996 -31970 -31968 -31951

--------------------------

normal:

    window rect: 176 232 877 627
menu bar "File": 180 262 208 281

--------------------------

maximized:

    window rect: -4 -4 1284 1028
menu bar "File": 0 26 28 45


it seems that, during WM_CREATE, the coordinates returned are those for a normal window, no mattter how the app is started
this is good to know   :U
while the values returned for a minimized window are offset by some strange neg value, they can still be used to some degree
you can still use them to calculate the size of the border and title bar, as well as the size of the menu item
the minimized window rectangle reflects the size on the task bar
minimizing multiple instances does not tell you the task bar position, though   :P

this applies to a window created with the WS_VISIBLE style bit set and...
CW_USEDEFAULT used for the x parameter
SW_SHOWWINDOW used for the y parameter
numeric values used for the nWidth and nHeight parameters
results may be different for different sets of parameters
but, for the most part, i think the conclusions are valid
Title: Re: Prevent Menu Wrap
Post by: dedndave on July 30, 2011, 03:36:50 PM
back to the code....
MichaelW made an interesting observation...
Quote... for the menu item coordinates to be useable the window must
initially be wide enough to prevent the menu from wrapping.

my solution is to tally the total widths for all items on the main menu
i get the same result whether the menu is wrapped or not
i will post the updated code sometime in the near future   :P
Title: Re: Prevent Menu Wrap
Post by: dedndave on July 31, 2011, 11:43:20 AM
ok - here we go   :P
this one works, even if the menu is initially wrapped
it will work for the normal, large, and extra large fonts in XP appearance settings

;MinWidth Include File - DednDave 7, 2011

;#############################################################################################################

MinWidth PROTO  :HWND,:UINT,:UINT

;#############################################################################################################

IFNDEF  MENUBARINFO
MENUBARINFO STRUCT
  cbSize           dd ?
  rcBar          RECT <>
  hMenu            dd ?
  hwndMenu         dd ?
  fBarFocused      dw ?
  fFocused         dw ?
MENUBARINFO ENDS
ENDIF

;#############################################################################################################

MinWidth PROC   uses esi edi hWnd:HWND,dwStyle:UINT,nMenuItemQty:UINT

;Find Minimum Window Width to Prevent Menu Wrap
;DednDave 7, 2011
;
;May be used in WM_CREATE, WM_THEMECHANGED, and in WM_SETTINGCHANGE when wParam = SPI_SETNONCLIENTMETRICS.
;The result value may then be saved and used in WM_GETMINMAXINFO to set MINMAXINFO.ptMinTrackSize.x.
;
;Call With:         hWnd = Main window handle
;                dwStyle = Style used for AdjustWindowRect; If WS_OVERLAPPEDWINDOW, use WS_THICKFRAME
;           nMenuItemQty = Number of main menu items
;
;  Returns:          EAX = Minimum window width
;
; Example: INVOKE  MinWidth,hWnd,WS_THICKFRAME,MAIN_MENU_ITEMS
;          mov     MinWindowWidth,eax

        mov     eax,nMenuItemQty
        or      eax,eax
        jz      MinWd1

        pushad
        xchg    eax,edi
        push    sizeof MENUBARINFO
        xor     esi,esi

MinWd0: INVOKE  GetMenuBarInfo,hWnd,OBJID_MENU,edi,esp
        add     esi,[esp].MENUBARINFO.rcBar.right
        sub     esi,[esp].MENUBARINFO.rcBar.left
        dec     edi
        jnz     MinWd0

        lea     eax,[esp].MENUBARINFO.hMenu
        INVOKE  GetWindowRect,hWnd,eax
        pop     edi                                      ;discard cbSize
        pop     eax                                      ;EAX = mb.left
        pop     ecx                                      ;ECX = mb.top
        pop     edi                                      ;discard mb.right
        pop     edx                                      ;EDX = mb.bottom
        pop     edi                                      ;EDI = wr.left
        sub     eax,edi                                  ;EAX = cr.left
        pop     edi                                      ;EDI = wr.top
        sub     ecx,edi                                  ;ECX = cr.top
        sub     edx,edi                                  ;EDX = cr.bottom
        add     esi,eax                                  ;ESI = cr.right
        push    edx                                      ;cr.bottom
        push    esi                                      ;cr.right
        push    ecx                                      ;cr.top
        push    eax                                      ;cr.left
        mov     edi,esp
        push    12                                       ;stack balance/magic number
        INVOKE  AdjustWindowRect,edi,dwStyle,TRUE
        pop     edx                                      ;EDX = 12
        pop     edi                                      ;discard wr.left (0)
        pop     ecx                                      ;ECX = wr.top (0)
        pop     eax                                      ;EAX = wr.right
        add     esp,edx
        add     eax,edx

MinWd1: ret

MinWidth ENDP

;#############################################################################################################

;End of WinWidth.inc
Title: Re: Prevent Menu Wrap
Post by: dedndave on July 31, 2011, 03:15:10 PM
ok - still working on this - lol
it seems that, during WM_THEMECHANGED and WM_SETTINGCHANGE,
there is a brief period of time when GetMenuBarInfo does not return correct rectangle values
furthermore, if i try to wait for the values to be correct, the system hangs   :bg
it is waiting for me to return 0 before completing the transition
strange, but i suppose it allows applications to make global changes during the switch

so - the above code works great, except when we need it to work   :lol
i will have to examine the message queue to see what all goes on for a solution
Title: Re: Prevent Menu Wrap
Post by: dedndave on August 04, 2011, 01:02:24 AM
as i said before, this is not as simple as it ought to be   :bg

i am using Display Properties, Appearance tab, Font Size to test my code
when the change is made, there is a sequence of messages....
hWin     unknown (31Bh)                 wParam: 00000000 lParam: 00000000
hWin     WM_WINDOWPOSCHANGING           wParam: 00000000 lParam: 0012F8B4
hWin     WM_NCCALCSIZE                  wParam: 00000001 lParam: 0012F888
hWin     WM_WINDOWPOSCHANGED            wParam: 00000000 lParam: 0012F8B4
hWin     WM_WINDOWPOSCHANGING           wParam: 00000000 lParam: 0012F938
hWin     WM_NCCALCSIZE                  wParam: 00000001 lParam: 0012F90C
hWin     WM_ERASEBKGND                  wParam: 92011145 lParam: 00000000
hWin     WM_WINDOWPOSCHANGED            wParam: 00000000 lParam: 0012F938
hWin     WM_NCCALCSIZE                  wParam: 00000001 lParam: 0012F568
hWin     unknown (31Bh)                 wParam: 0001001E lParam: 001001D1
hWin     WM_PAINT                       wParam: 00000000 lParam: 00000000
hWin     WM_CTLCOLORSCROLLBAR           wParam: 7C0104DC lParam: 003902E2
hWin     WM_CTLCOLORSCROLLBAR           wParam: 2401100D lParam: 004302FE
hWin     WM_SYSCOLORCHANGE              wParam: 00000000 lParam: 00000000
hWin     WM_SETTINGCHANGE               wParam: 00000000 lParam: 0012FF58
hWin     WM_SETTINGCHANGE               wParam: 00000000 lParam: 0012FF58
hWin     WM_SETTINGCHANGE               wParam: 0000000D lParam: 0012FF64
hWin     WM_SETTINGCHANGE               wParam: 00001023 lParam: 0012FF64
hWin     WM_SETTINGCHANGE               wParam: 00000018 lParam: 0012FF64
hWin     WM_SETTINGCHANGE               wParam: 00000018 lParam: 0012FF64
hWin     WM_GETMINMAXINFO               wParam: 00000000 lParam: 0012FD34
hWin     WM_NCCALCSIZE                  wParam: 00000001 lParam: 0012FF18
hWin     WM_WINDOWPOSCHANGED            wParam: 00000000 lParam: 0012FF44
hWin     WM_MOVE                        wParam: 00000000 lParam: 0038000E
hWin     WM_SIZE                        wParam: 00000000 lParam: 01240202
hWin     WM_CTLCOLORSCROLLBAR           wParam: D7010D70 lParam: 004302FE
hWin     WM_CTLCOLORSCROLLBAR           wParam: D7010D70 lParam: 003902E2
hWin     WM_NCCALCSIZE                  wParam: 00000001 lParam: 0012FB74
hWin     WM_SETICON                     wParam: 00000003 lParam: 00000000
hWin     WM_SETICON                     wParam: 00000003 lParam: 00000000
hWin     WM_GETICON                     wParam: 00000002 lParam: 00000000
hWin     WM_GETICON                     wParam: 00000000 lParam: 00000000
hWin     WM_GETICON                     wParam: 00000001 lParam: 00000000
hWin     WM_WINDOWPOSCHANGING           wParam: 00000000 lParam: 0012FD78
hWin     WM_NCCALCSIZE                  wParam: 00000001 lParam: 0012FD4C
hWin     WM_WINDOWPOSCHANGED            wParam: 00000000 lParam: 0012FD78
hWin     WM_WINDOWPOSCHANGED            wParam: 00000000 lParam: 0012FD78
hWin     WM_NCPAINT                     wParam: 00000001 lParam: 00000000
hWin     WM_SYNCPAINT                   wParam: 00000004 lParam: 00000000
hWin     WM_CTLCOLORSCROLLBAR           wParam: B90103E8 lParam: 003902E2
hWin     WM_CTLCOLORSCROLLBAR           wParam: B90103E8 lParam: 004302FE
hWin     WM_CTLCOLORSCROLLBAR           wParam: B90103E8 lParam: 004302FE


there are a few problems
one is, if you call GetMenuBarInfo during WM_SETTINGCHANGE code,
the size has not yet updated
if it is the middle of the change, the function may return RECT coordinates of 0
i tried "defering" the update until WM_GETMINMAXINFO
same thing happens
there is no clearly documented point in the sequence that may be used to know the change has taken affect

i wrote some code that creates a thread
it waits a period of time, then gets menu bar info, then updates
it works ok - but it does not seem a reliable method
it may work on one system with a certain set of time constants - but not on the next system
this is something that i may come back to later

for now........
;WM_GETMINMAXINFO

MinMx0: mov     edx,lParam
        mov     [edx].MINMAXINFO.ptMinTrackSize.x,208
        xor     eax,eax
        ret


:lol