VAN0 Posted June 15, 2020 Share Posted June 15, 2020 Hello. I can't seem to figure out why when #AutoIt3Wrapper_UseX64=Y is present, the $NM_CUSTOMDRAW notification is not firing: expandcollapse popup#AutoIt3Wrapper_UseX64=Y #include <GUIConstants.au3> #include <FontConstants.au3> #include <WinAPIShellEx.au3> #include <GuiListView.au3> Opt( "MustDeclareVars", 1 ) Global Const $tagNMCUSTOMDRAW = "struct;" & $tagNMHDR & ";dword dwDrawStage;handle hdc;" & $tagRECT & _ ";dword_ptr dwItemSpec;uint uItemState;lparam lItemlParam;endstruct" Global $hHeader Global $bgColor = 0x00FF00 Global $bgColorBrush = _WinAPI_CreateSolidBrush( $bgColor ) ; Brush with background color Example() Func Example() ; Create GUI GUICreate( "Styles, fonts, colors", 420, 320 ) ; Create ListView Local $idListView = GUICtrlCreateListView( "", 10, 10, 400, 300, -1, $WS_EX_CLIENTEDGE+$LVS_EX_FULLROWSELECT+$LVS_EX_HEADERDRAGDROP ) Local $hListView = GUICtrlGetHandle( $idListView ) $hHeader = _GUICtrlListView_GetHeader( $hListView ) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ; Add columns to ListView _GUICtrlListView_AddColumn( $hListView, "", 99 ) _GUICtrlListView_AddColumn( $hListView, "", 99 ) _GUICtrlListView_AddColumn( $hListView, "", 99 ) _GUICtrlListView_AddColumn( $hListView, "", 99 ) ; Fill ListView For $i = 0 To 9 GUICtrlCreateListViewItem( $i & "/1|" & $i & "/2|" & $i & "/3|" & $i & "/4", $idListView ) Next ; Show GUI GUISetState( @SW_SHOW ) ; Message loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _WinAPI_DeleteObject($bgColorBrush) GUIDelete() EndFunc Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam) Local $tNMHDR = DllStructCreate( $tagNMHDR, $lParam ) Local $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) ) Local $iCode = DllStructGetData( $tNMHDR, "Code" ) Switch $hWndFrom Case $hHeader Switch $iCode Case $NM_CUSTOMDRAW Local $tNMCustomDraw = DllStructCreate( $tagNMCUSTOMDRAW, $lParam ) Local $dwDrawStage = DllStructGetData( $tNMCustomDraw, "dwDrawStage" ) Switch $dwDrawStage ; Holds a value that specifies the drawing stage Case $CDDS_PREPAINT ; Before the paint cycle begins Return $CDRF_NOTIFYITEMDRAW ; Notify parent window of any item related drawing operations Case $CDDS_ITEMPREPAINT ; Before an item is drawn: Default painting (frames and background) Return $CDRF_NOTIFYPOSTPAINT ; Notify parent window of any post item related drawing operations Case $CDDS_ITEMPOSTPAINT ; After an item is drawn: Custom painting (item texts) Local $iIndex = DllStructGetData( $tNMCustomDraw, "dwItemSpec" ) ; Item index Local $hDC = DllStructGetData( $tNMCustomDraw, "hdc" ) ; Device context _WinAPI_SetBkMode( $hDC, $TRANSPARENT ) ; Transparent background ; set background color Local $tRECT = DllStructCreate( $tagRECT ) DllStructSetData( $tRECT, 1, DllStructGetData( $tNMCustomDraw, 6 ) + 1 ) DllStructSetData( $tRECT, 2, DllStructGetData( $tNMCustomDraw, 7 ) + 1 ) DllStructSetData( $tRECT, 3, DllStructGetData( $tNMCustomDraw, 8 ) - 2 ) DllStructSetData( $tRECT, 4, DllStructGetData( $tNMCustomDraw, 9 ) - 2 ) _WinAPI_FillRect( $hDC, $tRECT, $bgColorBrush ) ; First line DllStructSetData( $tNMCustomDraw, "Left", DllStructGetData( $tNMCustomDraw, "Left" ) + 2 ) ; Left margin DllStructSetData( $tNMCustomDraw, "Right", DllStructGetData( $tNMCustomDraw, "Right" ) - 2 ) ; Right margin DllStructSetData( $tNMCustomDraw, "Top", DllStructGetData( $tNMCustomDraw, "Top" ) + 2 ) ; 2 pixel top margin DllStructSetData( $tNMCustomDraw, "Bottom", DllStructGetData( $tNMCustomDraw, "Top" ) + 16 ) ; Line height DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", "Col" & $iIndex, "int", StringLen( "Col" & $iIndex ), "struct*", DllStructGetPtr( $tNMCustomDraw, "Left" ), "uint", $DT_CENTER ) ; _WinAPI_DrawText Return $CDRF_NEWFONT ; $CDRF_NEWFONT must be returned after changing font or colors EndSwitch EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc If #AutoIt3Wrapper_UseX64=Y removed, the listview header displays in green color as expected. Any ideas? Thank you. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted June 15, 2020 Moderators Share Posted June 15, 2020 (edited) VAN0, We discovered this same problem in my GUIListViewEx thread - LarsJ explains it in detail here. Not a lot you can do about it I am afraid, other then forcing to x86. M23 Edited June 15, 2020 by Melba23 Typo argumentum 1 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
VAN0 Posted June 15, 2020 Author Share Posted June 15, 2020 On 3/10/2019 at 4:43 PM, LarsJ said: Then I've replaced the GUIRegisterMsg technique with the Subclassing technique Here the code works in all 4 situations: Windows 7/10, 32/64 bit. In the GUIRegisterMsg example, only CDDS_PREPAINT notifications are displayed in SciTE console. The problem seems to be that the CDRF_NOTIFYITEMDRAW return values are not received by the operating system. Therefore, the operating system does not generate CDDS_ITEMPREPAINT or CDDS_ITEMPOSTPAINT notifications and the header items are not colored. Because the Subclassing example works, it excludes errors in the $tagNMLVCUSTOMDRAW structure. It seems like there is an error in the internal AutoIt code associated with the GUIRegisterMsg function when the code is run as 64 bit code. The return values from the WM_NOTIFY message handler are not properly forwarded to the operating system. The error seems also to be related to the fact that the header control is a second level child in relation to the GUI. Colors does work for a listview control which is a first level child. Solution: Implement the WM_NOTIFY message handler in GUIListViewEx.au3 using the Subclassing technique. This is not necessarily completely trivial. In my example above, it looks easy. But this is also a very small example. Lars. My understanding is that GUIRegisterMsg register callback for entire gui and it's content. So when I tried register $hGUI with Subclassing, it fails the same way GUIRegisterMsg does expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=y Opt( "MustDeclareVars", 1 ) #include <GUIConstants.au3> #include <GuiListView.au3> Global $hHeader, $aHdrTexts[8], $hGUI Example() Func Example() ; Create GUI $hGUI = GUICreate( "ListView Header Colors - Subclassing", 840, 420 ) ; Create ListView Local $idListView = GUICtrlCreateListView( "", 10, 10, 820, 400 ) _GUICtrlListView_SetExtendedListViewStyle ( $idListView, $LVS_EX_FULLROWSELECT ) ; Add columns to ListView For $i = 0 To 7 _GUICtrlListView_AddColumn( $idListView, "Column " & $i, 99 ) $aHdrTexts[$i] = "Column " & $i Next ; Fill ListView For $i = 0 To 99 GUICtrlCreateListViewItem( $i & "/0|" & $i & "/1|" & $i & "/2|" & $i & "/3|" & _ $i & "/4|" & $i & "/5|" & $i & "/6|" & $i & "/7|", $idListView ) Next ; Header control $hHeader = _GUICtrlListView_GetHeader( $idListView ) ; Register ListView WM_NOTIFY message handler Local $pLV_WM_NOTIFY = DllCallbackGetPtr( DllCallbackRegister( "LV_WM_NOTIFY", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) ) DllCall( "comctl32.dll", "bool", "SetWindowSubclass", "hwnd", $hGUI, "ptr", $pLV_WM_NOTIFY, "uint_ptr", 0, "dword_ptr", 0 ) ; $iSubclassId = 0, $pData = 0 ;_WinAPI_SetWindowSubclass( $hListView, $pLV_WM_NOTIFY, 0, 0 ) ; $iSubclassId = 0, $pData = 0 ; Show GUI GUISetState( @SW_SHOW ) ; Message loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $hGUI, "ptr", $pLV_WM_NOTIFY, "uint_ptr", 0 ) ; $iSubclassId = 0 ;_WinAPI_RemoveWindowSubclass( $hListView, $pLV_WM_NOTIFY, 0 ) ; $iSubclassId = 0 GUIDelete() EndFunc ; ListView WM_NOTIFY message handler Func LV_WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData ) If $iMsg <> 0x004E Then Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] ; 0x004E = $WM_NOTIFY Local Static $hHdrBrush = _WinAPI_CreateSolidBrush( 0xCCFFFF ) ; Yellow, BGR Local $tNMHDR = DllStructCreate( $tagNMHDR, $lParam ), $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) ), $iCode = DllStructGetData( $tNMHDR, "Code" ) Switch $hWndFrom Case $hHeader Switch $iCode Case $NM_CUSTOMDRAW Local $tNMCustomDraw = DllStructCreate( $tagNMLVCUSTOMDRAW, $lParam ) Local $dwDrawStage = DllStructGetData( $tNMCustomDraw, "dwDrawStage" ) Switch $dwDrawStage ; Holds a value that specifies the drawing stage Case $CDDS_PREPAINT ; Before the paint cycle begins ConsoleWrite( "CDDS_PREPAINT" & @CRLF ) Return $CDRF_NOTIFYITEMDRAW ; Notify parent window of any item related drawing operations Case $CDDS_ITEMPREPAINT ; Before an item is drawn: Default painting (frames and background) ConsoleWrite( "CDDS_ITEMPREPAINT" & @CRLF ) Return $CDRF_NOTIFYPOSTPAINT ; Notify parent window of any post item related drawing operations Case $CDDS_ITEMPOSTPAINT ; After an item is drawn: Custom painting (item texts) ConsoleWrite( "CDDS_ITEMPOSTPAINT" & @CRLF ) Local $iIndex = DllStructGetData( $tNMCustomDraw, "dwItemSpec" ) ; Item index Local $hDC = DllStructGetData( $tNMCustomDraw, "hdc" ) ; Device context _WinAPI_SetBkMode( $hDC, $TRANSPARENT ) ; Transparent background Local $tRECT = DllStructCreate( $tagRECT ) DllStructSetData( $tRECT, 1, DllStructGetData( $tNMCustomDraw, 6 ) + 1 ) DllStructSetData( $tRECT, 2, DllStructGetData( $tNMCustomDraw, 7 ) + 1 ) DllStructSetData( $tRECT, 3, DllStructGetData( $tNMCustomDraw, 8 ) - 2 ) DllStructSetData( $tRECT, 4, DllStructGetData( $tNMCustomDraw, 9 ) - 2 ) _WinAPI_FillRect( $hDC, $tRECT, $hHdrBrush ) ; Background color DllStructSetData( $tNMCustomDraw, "Left", DllStructGetData( $tNMCustomDraw, "Left" ) + 4 ) ; Left margin DllStructSetData( $tNMCustomDraw, "Right", DllStructGetData( $tNMCustomDraw, "Right" ) - 4 ) ; Right margin DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHdrTexts[$iIndex], "int", StringLen( $aHdrTexts[$iIndex] ), "struct*", DllStructGetPtr( $tNMCustomDraw, "Left" ), "uint", $DT_LEFT+$DT_SINGLELINE+$DT_VCENTER ) ; _WinAPI_DrawText Return $CDRF_NEWFONT ; $CDRF_NEWFONT must be returned after changing font or colors EndSwitch EndSwitch EndSwitch ; Call next function in subclass chain Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] #forceref $iSubclassId, $pData EndFunc Does it mean if we want use WM_NOTIFY for other components, we'll have to register separate function for each? Link to comment Share on other sites More sharing options...
VAN0 Posted June 15, 2020 Author Share Posted June 15, 2020 Thank you. I'll continue there than. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted June 15, 2020 Moderators Share Posted June 15, 2020 VAN0, No, please stick to your own thread as this has nothing to do with my UDF. M23 VAN0 1 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
VAN0 Posted June 15, 2020 Author Share Posted June 15, 2020 Thank you for moving my reply to this topic. So it seems even Subclassing has the same exact issue when it's register to GUI window itself, rather than to a specific control. Perhaps it's not GUIRegisterMsg issue after all . Link to comment Share on other sites More sharing options...
LarsJ Posted June 16, 2020 Share Posted June 16, 2020 An important information here is that WM_NOTIFY messages are sent to the parent window/control. Subclass the listview, which is the parent of the header control, instead of the GUI and the code will work. Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions 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