Jump to content

Recommended Posts

Hi.  Attempting to catch and process a keystroke in a GUI window.  Here's the code:

; ----------------------------------------------------------------------
; | Library includes
; ----------------------------------------------------------------------
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIListView.au3>
#include <WinAPISys.au3>
#include <WinAPIvkeysConstants.au3>
#include <GuiButton.au3>


global $g_MainGUI
CreateMainGUI()


; ----------------------------------------------------------------------
func CreateMainGUI()

    $g_MainGUI = GUICreate("Test", 600, 600, -1, -1)

;   $b = _GUICtrlButton_Create($g_MainGUI, "Foo", 10, 10, 100, 30)   ; <--- Line #21
    $lv = _GUICtrlListView_Create($g_MainGUI, "", 50, 50, 100, 100)  ; <--- Line #22

    GUISetState(@SW_SHOW, $g_MainGUI)
    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

    do
        ;
    until GUIGetMsg() = $GUI_EVENT_CLOSE
    GUIDelete()

endfunc


; ----------------------------------------------------------------------
func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

    local $hdr   = DllStructCreate($tagNMHDR, $lParam)
    local $from  = HWnd(DllStructGetData($hdr, "hWndFrom"))
    local $id    = DllStructGetData($hdr, "IDFrom")
    local $event = DllStructGetData($hdr, "Code")

    ; Exit on [ctrl-Q]
    if ($event = $LVN_KEYDOWN) then
        $info = DllStructCreate($tagNMLVKEYDOWN, $lParam)
        $vkey = DllStructGetData($info, "VKey")
        if ($vkey = 0x51) and BitAND(_WinAPI_GetKeyState($VK_CONTROL), 0x8000) then
            ConsoleWrite('[ctrl-Q]' & @CRLF)  ; <--- Line #48
            _SendMessage($g_MainGUI, $GUI_EVENT_CLOSE)
        endif
    endif

    return $GUI_RUNDEFMSG
endfunc

There are two things about this code that don't work the way I expected, and I've been unable to figure out why:

1)

As it stands, the code creates a GUI window, then a ListView.  If I run it then immediately press ctrl-Q, the keystroke triggers WM_NOTIFY().  I know that because if I run in SciTE, '[ctrl-Q]' appears in the console window, so the ConsoleWrite() call on line #48 must have executed.

If I comment out the _GUICtrlListView_Create() call on line #22 and uncomment line #21 so that a Button is created instead, then run it, WM_NOTIFY() is never triggered.

Why the difference?  Doesn't the GUIRegisterMsg() call register WM_NOTIFY on behalf of the parent GUI?  Why does it work with one control type, but not the other?

2)

In the case with the ListView control, where it does catch the ctrl-Q, it executes _SendMessage($g_MainGUI, $GUI_EVENT_CLOSE).  In my simple mind, I'd have thought that would send the $GUI_EVENT_CLOSE message to the main GUI and cause it to exit the do/until loop.

But evidently not?  Because it doesn't.

Thanks in advance.  Just when I think I understand ...

/John

Share this post


Link to post
Share on other sites
Posted (edited)

1)  Not all messages are sent/received to all controls.  WM_NOTIFY has its own particularities.  It is by experimenting that you will learn which messages transit in windows.  You can also use a message catcher to grab all the messages directed to a window.  There are multiple examples made here.

2) The right message is $WM_CLOSE. (MSDN is the bible). There is also a list in appendix of help File. 

Edited by Nine

Share this post


Link to post
Share on other sites
Posted (edited)

1) You are catching only specific ListView's message

if ($event = $LVN_KEYDOWN)

LVN_xxx - means ListView Notification message

 

That's why it will not catch button message, there are different Buttons specific notification messages --> BN_CLICKED, BN_DBLCLK, ... (see "c:\Program Files\AutoIt3\Include\ButtonConstants.au3" )

Edited by Zedna

Share this post


Link to post
Share on other sites

Thank you both for your help.  I've got much to learn ...

Actually, for the specific thing I was trying to do (simply exit when ctrl-Q is hit), I found I could rather easily accomplish it with HotKeySet().  But I'm still the sort of person who wonders why something didn't work that I thought would, even if I don't necessarily need it anymore.  (That's how we learn.)

Zedna:  I didn't realize that the LVN prefix meant ListView Notification -- somehow missed that.  That will definitely help to know.

Nine:  By ' You can also use a message catcher to grab all the messages directed to a window', are you thinking of _WinAPI_SetWindowsHookEx()?

Last comment:  I thought of $WM_CLOSE.  In fact, getting a window to close isn't too hard (the HotKeySet() solution simply Exit's).  But I thought the 'right' (in some sense, cleaner) way to do it would be to somehow get the $GUI_EVENT_CLOSE to the GUI, so that the do/until loop would terminate, and then the script would exit properly through the end.  I guess I still don't know why it doesn't work.

Thanks again!

Share this post


Link to post
Share on other sites
2 minutes ago, DrJohn said:

are you thinking of _WinAPI_SetWindowsHookEx()?

No I meant a program that will monitor message transitions in a GUI.  As for example :

 

 

12 minutes ago, DrJohn said:

I guess I still don't know why it doesn't work.

It is because $GUI_EVENT_CLOSE is not a message nor a notification (it is an internal GUI event).  By sending $WM_CLOSE, the GUI will react to it and generate the $GUI_EVENT_CLOSE event.

Share this post


Link to post
Share on other sites
Posted (edited)

Thank you again.  This really helps my understanding!

As I said, I've got a lot to learn.  (I see that my profile even says I'm a 'Seeker'.  It's like it knows me ...)

(FWIW, I should have intuited that $GUI_EVENT_CLOSE is not a Windows message.  That was kind of dense on my part.)

I appreciate your insight.

/John

Edited by DrJohn

Share this post


Link to post
Share on other sites

Hi again Nine.  If you'd be willing to push this a step further:

You are right.  Sending $WM_CLOSE does cause the GUI to receive $GUI_EVENT_CLOSE, and the do/until loop terminates as expected.  Cool!

So here's a similar example, but this one uses $WM_KEYDOWN instead:

; ----------------------------------------------------------------------
; | Library includes
; ----------------------------------------------------------------------
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIListView.au3>
#include <WinAPISys.au3>
#include <WinAPIvkeysConstants.au3>


global $g_MainGUI
CreateMainGUI()


; ----------------------------------------------------------------------
func CreateMainGUI()

    $g_MainGUI = GUICreate("Test", 600, 600, -1, -1)
;   $lv = _GUICtrlListView_Create($g_MainGUI, "", 50, 50, 100, 100)  ; <--- Line #19

    GUISetState(@SW_SHOW, $g_MainGUI)
    GUIRegisterMsg($WM_KEYDOWN, "WM_KEYDOWN")

    do
        ;
    until GUIGetMsg() = $GUI_EVENT_CLOSE
    GUIDelete()

endfunc


; ----------------------------------------------------------------------
func WM_KEYDOWN($hWnd, $iMsg, $wParam, $lParam)

    if ($wParam = 0x51) and BitAND(_WinAPI_GetKeyState($VK_CONTROL), 0x8000) then
        _SendMessage($g_MainGUI, $WM_CLOSE)
    endif

    return $GUI_RUNDEFMSG
endfunc

This works just as expected, if the _GUICtrlListView_Create() on line #19 is commented out.  The GUI detects the $WM_KEYDOWN event, WM_KEYDOWN() sends a $WM_CLOSE, and the GUI exits.

Uncomment line #19 so that a ListView is created, and it no longer works that way.  Is it reasonable to assume the ListView is somehow catching and eating the $WM_KEYDOWN message before the main GUI can see it?

(I have downloaded and taken a quick look at Larsj's Windows Message Monitor, and I suspect using it, I can find out ...)

/John

Share this post


Link to post
Share on other sites

Follow-up:

Using the Windows Message Monitor, it seems I can verify that in the version that creates the ListView, when I hit ctrl-Q it is the Listview that receives the $WM_KEYDOWN message, rather than the main GUI.

I guess what surprises me is that the registered function WM_KEYDOWN() doesn't get called all the same, since the ListView is a child control of the main GUI.

Image 1.png

Share this post


Link to post
Share on other sites

Glad you sort it out.  Yes it is the ListView that receives the $WM_KEYDOWN message.  You can register message at control level either using _WinAPI_SetWindowLong or with the Win32 API SetWindowSubclass (google the last in MSDN).

There is a good example of using _WinAPI_SetWindowLong in help file under _WinAPI_CallWindowProc (this approach I recommend as you have more documentation of how to implement it in AutoIt)

Share this post


Link to post
Share on other sites
Posted (edited)

Look at GUISetAccelerators() which is exactly what you need for your hotkey: Ctrl+Q = Exit

This way it will work with and/or without ListView :-)

https://www.autoitscript.com/autoit3/docs/functions/GUISetAccelerators.htm

 

EDIT:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIListView.au3>
#include <WinAPISys.au3>

global $g_MainGUI
CreateMainGUI()

func CreateMainGUI()

    $g_MainGUI = GUICreate("Test", 600, 600, -1, -1)
    $idUserExit = GUICtrlCreateDummy()
 ;   $lv = _GUICtrlListView_Create($g_MainGUI, "", 50, 50, 100, 100)  ; <--- Line #19

    Local $aAccelKeys[1][2] = [["^q", $idUserExit]]
    GUISetAccelerators($aAccelKeys)

    GUISetState(@SW_SHOW, $g_MainGUI)

    do
        $msg = GUIGetMsg()
        If $msg = $idUserExit Then _SendMessage($g_MainGUI, $WM_CLOSE)
        
    until $msg = $GUI_EVENT_CLOSE
    GUIDelete()

endfunc

 

Edited by Zedna

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Irios
      I have several context menus that's been built using _GUICtrlMenu_CreatePopup() and _GUICtrlMenu_AddMenuItem().
      When using _GUICtrlMenu_CreatePopup() it returns the identifier of the clicked item, sure. But it blocks the main loop while the menu is open.
      When using _GUICtrlMenu_CreatePopup($MNS_MODELESS) it returns immediately (of course), but I cannot figure out how/where to read the item that was clicked. Is there a Windows Message (WM) somewhere that is triggered? I've spend an entire day trying to figure out how to do this, but I'm not getting anywhere. My google fu is depleted (I must have tried like hundreds of script variations today), I'm about to smash my keyboard and just go to bed, and abandon the entire endeavor of making pretty menus and go back to using Koda and forget about using menu icons, colors,  etc.
      Anyone wanna help me out with how to read the clicked item? Before I smash my keyboard, please...
       
      Example script here:
       
      #include <GuiMenu.au3> #include <WinAPIError.au3> #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> GUIRegisterMsg($WM_CONTEXTMENU, "_WM_CONTEXTMENU") Global $idMenuItem = 10000, $counter = 0 Global $hGUI = GUICreate("Menu test", 400, 300) Global $hListview = GUICtrlCreateListView("", 2, 2, 396, 200) GUISetState(@SW_SHOW) ;~ Global $hMenuContext = _GUICtrlMenu_CreatePopup() Global $hMenuContext = _GUICtrlMenu_CreatePopup($MNS_MODELESS) _GUICtrlMenu_AddMenuItem($hMenuContext, "Menu item", $idMenuItem) Global $hTimer = TimerInit() Do If TimerDiff($hTimer)>200 Then $counter += 1 ConsoleWrite($counter & " " ) $hTimer = TimerInit() EndIf Until GUIGetMsg() = $GUI_EVENT_CLOSE Exit Func _WM_CONTEXTMENU($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $lParam Switch $wParam Case GUICtrlGetHandle($hListview) ConsoleWrite( @CRLF & "_GUICtrlMenu_TrackPopupMenu = " & _GUICtrlMenu_TrackPopupMenu($hMenuContext, $wParam, -1, -1, 1, 1, 2) & @CRLF) EndSwitch EndFunc  
       
    • By Skysnake
      Hi
      Best example I could find is here
      ::/html/libfunctions/_GUICtrlTreeView_ClickItem.htm
      The way I understand this, the standard Windows messages, such as Left/Right Click etc are covered by AutoIt macros, but the real power is locked up inside this WM_NOTIFY .  I have tried, but I am not even sure I understand what I am looking at.
      I need help understanding this.  What I am looking for is Help file or Tutorial explaining how this works?  
      Perhaps if there is a script showing both the working of an AutoIt macro and the WM_NOTIFY  in action, it would help.
      Right now I am so lost, I do not even know what are the right questions to ask.  One issue I have is on ListViews, how to combine the "Click" of a line with a standard Switch loop?  Like users clicks a line, then get the loop to detect the click and ;do something ...
      Any ideas?
      Skysnake
    • By AutoBert
      I have a LV with different coloured Cols:
      ;https://autoit.de/index.php/Thread/84279-Unterschiedliche-Textfarben-innerhalb-einer-ListView/?postID=674195#post674195 #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <array.au3> #include <ListViewConstants.au3> #include <StructureConstants.au3> #include <WindowsConstants.au3> $aColBK = IniReadSection(@ScriptDir & "\lv_format.ini", "ColBKColor") _ArrayDelete($aColBK, 0) ;_ArrayDisplay($aColBK) $aRowBK = IniReadSection(@ScriptDir & "\lv_format.ini", "RowBKColor") _ArrayDelete($aRowBK, 0) ;_ArrayDisplay($aColBK) $aColText = IniReadSection(@ScriptDir & "\lv_format.ini", "ColTextColor") _ArrayDelete($aColText, 0) ;_ArrayDisplay($aColBK) $aRowText = IniReadSection(@ScriptDir & "\lv_format.ini", "RowTextColor") _ArrayDelete($aRowText, 0) ;_ArrayDisplay($aRowText) $GUI = GUICreate("Listview Farbig", 1024, 300, 0, 0) ;<==== Breite geändert $cListView = GUICtrlCreateListView("", 2, 2, 1020, 294, -1, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT)) ;<==== Breite geändert $hListView = GUICtrlGetHandle($cListView) For $i = 1 To 31 _GUICtrlListView_InsertColumn($hListView, $i - 1, $i, 25) _GUICtrlListView_SetColumnWidth($hListView, $i - 1, 32) ;<==== eingefügt für Spaltenbreite Next For $i = 0 To 21 ; alle Item/SubItem erstellen _GUICtrlListView_AddItem($hListView, "Item: " &$i, $i) For $j = 1 To 30 _GUICtrlListView_AddSubItem($hListView, $i, "Sub: "&$j, $j) Next Next GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() While True $msg = GUIGetMsg() Switch $msg Case -3 ExitLoop EndSwitch WEnd Func WM_NOTIFY($hWnd, $msg, $wParam, $lParam) Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $hListView Switch $iCode Case $NM_CUSTOMDRAW Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam) Local $iDrawStage, $iItem, $iSubitem, $hDC, $tRect $iDrawStage = DllStructGetData($tCustDraw, 'dwDrawStage') Switch $iDrawStage Case $CDDS_ITEMPREPAINT Return $CDRF_NOTIFYSUBITEMDRAW Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM) ; Item/SubItem das aktuell gezeichnet werden soll ermitteln $iItem = DllStructGetData($tCustDraw, 'dwItemSpec') $iSubitem = DllStructGetData($tCustDraw, 'iSubItem') Switch $iItem ; Zeilenwahl Case -1 ;kommt nicht vor ist aber notwendig, damit case else verwendet werden kann Case Else $iIndex = _ArraySearch($aRowBK, $iItem, 0, 0, 0, 0, 1, 0) If $iIndex = -1 Then ;nicht im Array für spezielle Zeilen also weiß DllStructSetData($tCustDraw, 'clrTextBk', RGB2BGR(0xFFFFFF)) Else DllStructSetData($tCustDraw, 'clrTextBk', RGB2BGR($aRowBK[$iIndex][1])) ;ConsoleWrite('Item '&$iItem&' BK: '&$aRowBK[$iIndex][1] & @CRLF) EndIf $iIndex = _ArraySearch($aRowText, $iItem, 0, 0, 0, 0, 1, 0) If $iIndex = -1 Then ;nicht im Array für spezielle Zeilen also schwarz DllStructSetData($tCustDraw, 'clrText', RGB2BGR(0x000000)) Else DllStructSetData($tCustDraw, 'clrText', RGB2BGR($aRowText[$iIndex][1])) ;ConsoleWrite('Item '&$iItem&' Text: '&$aRowText[$iIndex][1] & @CRLF) EndIf EndSwitch Switch $iSubitem Case -1 ;kommt nicht vor ist aber notwendig, damit case else verwendet werden kann Case Else $iIndex = _ArraySearch($aColBK, $iSubitem, 0, 0, 0, 0, 1, 0) If $iIndex <> -1 Then DllStructSetData($tCustDraw, 'clrTextBk', RGB2BGR($aColBK[$iIndex][1])) ;ConsoleWrite('SubItem '&$iSubitem&' BK: '&$aColBK[$iIndex][1] & @CRLF) EndIf $iIndex = _ArraySearch($aColText, $iSubitem, 0, 0, 0, 0, 1, 0) If $iIndex <> -1 Then DllStructSetData($tCustDraw, 'clrText', RGB2BGR($aColText[$iIndex][1])) ;ConsoleWrite('SubItem '&$iSubitem&' Text: '&$aColText[$iIndex][1] & @CRLF) EndIf EndSwitch Return $CDRF_NEWFONT EndSwitch EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Func RGB2BGR($iColor) Local $sH = Hex($iColor, 6) Return '0x' & StringRight($sH, 2) & StringMid($sH, 3, 2) & StringLeft($sH, 2) EndFunc ;==>RGB2BGR i use lv_format.ini for defining the cols Background- and Textcolour. Now i want to colour the cols in the LV-Header also, but i can't figure it out.
       

    • By kcvinu
      Hi all,
      I am trying to get the selected item text from a tree view control.
      For that i am using this code. Please take a look. In this code, i am using console write function so that i am able to know that the user clicks in an item. This code works perfectly at the first click. But when i click on an item second time, it will work twice, That means, console write will work twice. Same result is at the third and fourth click also. 
       
      Func TreeView_WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndTreeview $hWndTreeview = $tv1 If Not IsHWnd($tv1) Then $hWndTreeview = GUICtrlGetHandle($tv1) $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $hWndTreeview Switch $iCode Case $TVN_SELCHANGINGW ConsoleWrite("Clicked" & @CRLF) EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY  
    • By DavidStark
      Hey guys,
      After much searching and reading I Siao's example script from the below link is the closest to what I need to do.
      I have a ListView that is populated with the names of different configurations.  When a Listview item is selected, a form is populated with that items data.  Right now I have a column that shows which item's data is shown in the form, but it would be much cleaner to just have the current item highlighted.
      My problem is this - The highlighting in Siao's example works great, but inside the Listview when you select in the "empty" space to essentially deselect everything the highlighting disappears.
      How can I keep the last selected item highlighted when clicking in this empty space?
      Also - I do not understand enough about Windows notifications to understand if we could utilize SendMessage to initiate a custom draw....  It seems to me that you could specify an item and then invoke the DLL function to redraw the item that you specified with the colors that you specified.... That's the idea I get when I read the MSDN documentation on it: https://msdn.microsoft.com/en-us/library/windows/desktop/ff919573(v=vs.85).aspx
       
      Siao's Example modified for latest AutoIt:
      #Include <GuiConstantsEx.au3> #Include <GuiListView.au3> #include <WindowsConstants.au3> #cs ;custom draw constants Global Const $CDDS_ITEM = 0x10000 Global Const $CDDS_MAPPART = 0x5 Global Const $CDDS_POSTERASE = 0x4 Global Const $CDDS_POSTPAINT = 0x2 Global Const $CDDS_PREERASE = 0x3 Global Const $CDDS_PREPAINT = 0x1 Global Const $CDDS_SUBITEM = 0x20000 Global Const $CDDS_ITEMPOSTERASE = BitOR($CDDS_ITEM, $CDDS_POSTERASE) Global Const $CDDS_ITEMPOSTPAINT = BitOR($CDDS_ITEM, $CDDS_POSTPAINT) Global Const $CDDS_ITEMPREERASE = BitOR($CDDS_ITEM, $CDDS_PREERASE) Global Const $CDDS_ITEMPREPAINT = BitOR($CDDS_ITEM, $CDDS_PREPAINT) Global Const $CDIS_CHECKED = 0x8 Global Const $CDIS_DEFAULT = 0x20 Global Const $CDIS_DISABLED = 0x4 Global Const $CDIS_FOCUS = 0x10 Global Const $CDIS_GRAYED = 0x2 Global Const $CDIS_HOT = 0x40 Global Const $CDIS_INDETERMINATE = 0x100 Global Const $CDIS_MARKED = 0x80 Global Const $CDIS_SELECTED = 0x1 Global Const $CDIS_SHOWKEYBOARDCUES = 0x200 Global Const $CDRF_DODEFAULT = 0x0 Global Const $CDRF_NEWFONT = 0x2 Global Const $CDRF_NOTIFYITEMDRAW = 0x20 Global Const $CDRF_NOTIFYPOSTERASE = 0x40 Global Const $CDRF_NOTIFYPOSTPAINT = 0x10 Global Const $CDRF_NOTIFYSUBITEMDRAW = 0x20 Global Const $CDRF_SKIPDEFAULT = 0x4 #ce ;fonts for custom draw example ;bold Global $aFont1 = DLLCall("gdi32.dll","int","CreateFont", "int", 14, "int", 0, "int", 0, "int", 0, "int", 700, _ "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, _ "dword", 0, "str", "") ;italic Global $aFont2 = DLLCall("gdi32.dll","int","CreateFont", "int", 14, "int", 0, "int", 0, "int", 0, "int", 400, _ "dword", 1, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, _ "dword", 0, "str", "") $GUI = GUICreate("Listview Custom Draw", 400, 300) $cListView = GUICtrlCreateListView("", 2, 2, 394, 268, -1, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT)) $hListView = GUICtrlGetHandle($cListView) _GUICtrlListView_InsertColumn($hListView, 0, "Column 1", 100) _GUICtrlListView_InsertColumn($hListView, 1, "Column 2", 100) _GUICtrlListView_InsertColumn($hListView, 2, "Column 3", 100) ; Add items For $i = 1 To 30 _GUICtrlListView_AddItem($hListView, "Row" & $i & ": Col 1", $i-1) For $j = 1 To 2 _GUICtrlListView_AddSubItem ($hListView, $i-1, "Row" & $i & ": Col " & $j+1, $j) Next Next GUICtrlCreateInput("", 50, 275, 100, 15) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE DLLCall("gdi32.dll","int","DeleteObject", "hwnd", $aFont1[0]) DLLCall("gdi32.dll","int","DeleteObject", "hwnd", $aFont2[0]) Exit Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam) Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $hListView Switch $iCode Case $NM_CUSTOMDRAW If Not _GUICtrlListView_GetViewDetails($hWndFrom) Then Return $GUI_RUNDEFMSG Local $tCustDraw = DllStructCreate('hwnd hwndFrom;int idFrom;int code;' & _ 'dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;' & _ 'dword clrText;dword clrTextBk;int SubItem;' & _ 'dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align', _ ;winxp or later $lParam), $iDrawStage, $iItem, $iSubitem, $hDC, $tRect, $iColor1, $iColor2, $iColor3 $iDrawStage = DllStructGetData($tCustDraw, 'DrawStage') Switch $iDrawStage Case $CDDS_PREPAINT Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT Return $CDRF_NOTIFYSUBITEMDRAW Case $CDDS_ITEMPOSTPAINT Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM) $iItem = DllStructGetData($tCustDraw, 'ItemSpec') $iSubitem = DllStructGetData($tCustDraw, 'SubItem') If _GUICtrlListView_GetItemSelected($hWndFrom, $iItem) Then $hDC = _WinAPI_GetDC($hWndFrom) $tRect = DllStructCreate('long;long;long;long') If $iSubitem = 0 Then DllCall('user32.dll','int','SendMessage', 'hwnd',$hWndFrom, 'uint',$LVM_GETSUBITEMRECT, 'wparam',$iItem, 'lparam',DllStructGetPtr($tRect)) DllStructSetData($tRect, 1, 2) DllCall('user32.dll', 'int', 'FillRect', 'ptr', $hDC, 'ptr', DllStructGetPtr($tRect), 'int', _WinAPI_GetStockObject(4)) EndIf DllStructSetData($tRect, 1, 2) DllStructSetData($tRect, 2, $iSubitem) DllCall('user32.dll','int','SendMessage', 'hwnd',$hWndFrom, 'uint',$LVM_GETSUBITEMRECT, 'wparam',$iItem, 'lparam',DllStructGetPtr($tRect)) Local $sText = _GUICtrlListView_GetItemText($hWndFrom, $iItem, $iSubitem) DLLCall("gdi32.dll","int","SetTextColor", "ptr", $hDC, "int", RGB2BGR(0xffff00)) DLLCall("gdi32.dll","int","SetBkMode", "ptr", $hDC, "int", 1) DllStructSetData($tRect, 1, DllStructGetData($tRect, 1)+2) _WinAPI_DrawText($hDC, $sText, $tRect, 0x8000) ;; $DT_END_ELLIPSIS _WinAPI_ReleaseDC($hWndFrom, $hDC) Return $CDRF_SKIPDEFAULT EndIf Switch $iItem Case 0 To 9 ;for rows 1-10 lets do this $iColor1 = RGB2BGR(0xFBFFD8) $iColor2 = RGB2BGR(-1) $iColor3 = RGB2BGR(0xFF0000) If Mod($iSubitem, 2) Then ;odd columns DllStructSetData($tCustDraw, 'clrTextBk', $iColor1) DllStructSetData($tCustDraw, 'clrText', 0) Else ;even columns DllStructSetData($tCustDraw, 'clrTextBk', $iColor2) DllStructSetData($tCustDraw, 'clrText', $iColor3) EndIf Case 10 To 19 ;for rows 11-20 lets do this $iColor1 = RGB2BGR(0xFBFFD8) $iColor2 = RGB2BGR(0x3DF8FF) $hDC = DllStructGetData($tCustDraw, 'hdc') If Mod($iItem, 2) Then If Mod($iSubitem, 2) Then DllStructSetData($tCustDraw, 'clrTextBk', $iColor1) Else DllStructSetData($tCustDraw, 'clrTextBk', $iColor2) EndIf DLLCall("gdi32.dll","hwnd","SelectObject", "hwnd", $hDC, "hwnd", $aFont1[0]) ;select our chosen font into DC Else If Mod($iSubitem, 2) Then DllStructSetData($tCustDraw, 'clrTextBk', $iColor2) Else DllStructSetData($tCustDraw, 'clrTextBk', $iColor1) EndIf DLLCall("gdi32.dll","hwnd","SelectObject", "hwnd", $hDC, "hwnd", $aFont2[0]) EndIf Case 20 To 29 ;for rows 21-30 lets do this $iColor1 = RGB2BGR(0xFBFFD8) $iColor2 = RGB2BGR(-1) If Mod($iItem, 2) Then ;odd rows DllStructSetData($tCustDraw, 'clrTextBk', $iColor2) Else DllStructSetData($tCustDraw, 'clrTextBk', $iColor1) EndIf EndSwitch Return $CDRF_NEWFONT Case BitOR($CDDS_ITEMPOSTPAINT, $CDDS_SUBITEM) Case Else EndSwitch EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Func RGB2BGR($iColor) Return BitAND(BitShift(String(Binary($iColor)), 8), 0xFFFFFF) EndFunc Source:
       
×
×
  • Create New...