orbs Posted March 26, 2015 Share Posted March 26, 2015 suppose you want to display only a single large control, e.g. a ListView. you have a lot of data, but it may be viewed on a small-screen device. you care about not wasting screen area, but you need at least a few basic operations. sure you could use a menu bar, but real estate is pricey these days... inspired by >this - but not even remotely similar in implementation - let's click on the title bar caption text to pop-up a menu! (while clicking on the vacant area of the title bar is used for dragging, as usual). first let's add a small drop-down-like sign to indicate it's possible to click on the caption text: (the red line indicates the width of the title bar that when clicked will pop-up a menu. it is slightly extended, to compensate for situations where the font is larger. it is here for illustration only). the menu is designed as usual, but triggered by registering the WM_SYSCOMMAND message, and checking that the cursor is at the correct position. unfortunately, Windows XP/2003 do not render extended characters (well or at all), so a standard character was selected for them - see screenshots below. Windows Vista also does a poor job at it. but even more unfortunately, Windows 8 has the title bar caption centered! so here's a quick'n'dirty solution: extend the caption with a lot of whitespaces. this has two side effects - there's the 3-dots sign near the "Minimize" button, and the taskbar icon tooltip is extended. i can live with that... so this is how it looks: Windows 8: Windows Vista: Windows XP: Windows 2000 (for the classic theme): the script (uses >_StringSize by Melba23, but you can set the size fix according to your needs): expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include "StringSize.au3" Global $nGUI_W = 700, $nGUI_H = 500 Global $sTitle = 'My Program Title' Global $nOSVersion = _OSVersion() If $nOSVersion < 6 Then ; not rendering ChrW well $sTitle = ' :: ' & $sTitle Else $sTitle &= ' ' & ChrW(9662) EndIf Global $aTitleWidth = _StringSize($sTitle) Global $iTitleWidth = 0 If Not @error Then $iTitleWidth = $aTitleWidth[2] + 3 ; ampirical Global $iTitleOffset = 20 ; ampirical: 16px icon + 4px space If $nOSVersion > 6.1 Then ; Windows 8, Windows 2012 => "align" caption to left, consider increased font size $sTitle &= ' ' $iTitleOffset = $iTitleOffset * 1.2 ; ampirical EndIf $iTitleWidth = $iTitleWidth * 1.3 ; ampirical Global $hGUI = GUICreate($sTitle, $nGUI_W, $nGUI_H, -1, -1, BitOR($WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_SYSMENU)) ; indicative label for the position and width of titlebar caption text to trigger menu GUICtrlCreateLabel('', $iTitleOffset, 0, $iTitleWidth, 1) GUICtrlSetResizing(-1, $GUI_DOCKALL) GUICtrlSetBkColor(-1, 0xff0000) Global $gMenu_Dummy = GUICtrlCreateDummy() Global $gMenu = GUICtrlCreateContextMenu($gMenu_Dummy) Global $gMenu_Submenu = GUICtrlCreateMenu('Submenu', $gMenu) Global $gMenu_Option = GUICtrlCreateMenuItem('Option', $gMenu) Global $bOption = True GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlCreateMenuItem('', $gMenu) For $i = 1 To 5 GUICtrlCreateMenuItem('Submenu Item ' & $i, $gMenu_Submenu) GUICtrlSetState(-1, $GUI_CHECKED) Next GUICtrlCreateMenuItem('Item 1', $gMenu) GUICtrlCreateMenuItem('Item 2', $gMenu) GUICtrlCreateMenuItem('Item 3', $gMenu) GUICtrlCreateMenuItem('', $gMenu) Global $gMenu_About = GUICtrlCreateMenuItem('About', $gMenu) Global $gMenu_Close = GUICtrlCreateMenuItem('Close', $gMenu) GUISetState(@SW_SHOW, $hGUI) GUIRegisterMsg($WM_SYSCOMMAND, '_WM_SYSCOMMAND') GUIRegisterMsg($WM_GETMINMAXINFO, "_WM_GETMINMAXINFO") Global $msg While True $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE, $gMenu_Close ExitLoop Case $gMenu_Option $bOption = Not $bOption If $bOption Then GUICtrlSetState($gMenu_Option, $GUI_CHECKED) Else GUICtrlSetState($gMenu_Option, $GUI_UNCHECKED) EndIf EndSwitch WEnd #region context menu and auxiliary funcs Func _ContextMenu_ShowMenu($hWnd, $nContextID, $CtrlID = 0, $n_dx = 0, $n_dy = 0) ; Show a menu in a given GUI window which belongs to a given GUI ctrl Local $arPos[4], $x, $y Local $hMenu = GUICtrlGetHandle($nContextID) If $CtrlID Then $arPos = ControlGetPos($hWnd, "", $CtrlID) $x = $arPos[0] + $n_dx $y = $arPos[1] + $arPos[3] + $n_dy _ContextMenu_ClientToScreen($hWnd, $x, $y) _ContextMenu_TrackPopupMenu($hWnd, $hMenu, $x, $y) EndFunc ;==>_ContextMenu_ShowMenu Func _ContextMenu_ClientToScreen($hWnd, ByRef $x, ByRef $y) ; Convert the client (GUI) coordinates to screen (desktop) coordinates Local $stPoint = DllStructCreate("int;int") DllStructSetData($stPoint, 1, $x) DllStructSetData($stPoint, 2, $y) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint)) $x = DllStructGetData($stPoint, 1) $y = DllStructGetData($stPoint, 2) ; release Struct not really needed as it is a local $stPoint = 0 EndFunc ;==>_ContextMenu_ClientToScreen Func _ContextMenu_TrackPopupMenu($hWnd, $hMenu, $x, $y) ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0) EndFunc ;==>_ContextMenu_TrackPopupMenu Func _WM_SYSCOMMAND($hWnd, $iMsg, $wParam, $lParam) ; to display main menu when click titlebar caption #forceref $hWnd, $iMsg, $wParam, $lParam Local $iMousePos Local $iClientAreaPosX, $iClientAreaPosY If $wParam = 0x0000F012 Then $iMousePos = MouseGetPos(0) _ContextMenu_ClientToScreen($hGUI, $iClientAreaPosX, $iClientAreaPosY) If $iMousePos > $iClientAreaPosX + $iTitleOffset And $iMousePos < $iClientAreaPosX + $iTitleOffset + $iTitleWidth Then _ContextMenu_ShowMenu($hWnd, $gMenu) EndIf EndFunc ;==>_WM_SYSCOMMAND Func _WM_GETMINMAXINFO($hWnd, $iMsg, $wParam, $lParam) ; to enforce minimum window size #forceref $hWnd, $iMsg, $wParam, $lParam Local $tagMaxinfo If $hWnd = $hGUI Then $tagMaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam) DllStructSetData($tagMaxinfo, 7, $nGUI_W - 100) DllStructSetData($tagMaxinfo, 8, $nGUI_H - 100) Return 0 EndIf EndFunc ;==>_WM_GETMINMAXINFO Func _OSVersion() $sOSVersion = RegRead('HKLM\Software\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion') If @error Then Return SetError(1, 0, 0) Return Number($sOSVersion) EndFunc ;==>_OSVersion #endregion context menu and auxiliary funcs the entire thing is as crude as hell, and i'm sure there are many more elegant ways to improve it. enjoy! argumentum, coffeeturtle and JohnOne 3 Signature - my forum contributions: Spoiler UDF: LFN - support for long file names (over 260 characters) InputImpose - impose valid characters in an input control TimeConvert - convert UTC to/from local time and/or reformat the string representation AMF - accept multiple files from Windows Explorer context menu DateDuration - literal description of the difference between given dates Apps: Touch - set the "modified" timestamp of a file to current time Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes SPDiff - Single-Pane Text Diff Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now