Jump to content



Photo

Custom ListView - icons / checkboxes / multiline / edit in place


  • Please log in to reply
25 replies to this topic

#1 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 06 April 2012 - 03:17 AM

EDIT: Along the following posts you will encounter a series of examples, tricks and workarounds, showing you how to accomplish:
- custom fonts, font colors and row colors (selected/unselected)
- icons / checkboxes on items and subitems
- multiline rows in listviews
- themed listviews

Performance-wise, rover's example in post #17 is very optimized.
Working examples of Edit in Place are postponed for now.
________________________

Hi guys,

I'm trying to find some example code of a List with several sub-items (columns), with the possibility of including icons (preferably embedded in the compiled executable) and more than one checkbox per row.

A while back (maybe a year or so), I came across an example of a ListView that had all this customization: icons / colored boxes, checkboxes and edit in place.

But I'm not entirely sure if it had all three combined.
I mean, I'm not even sure if the control was actually a ListView, but it surely resembled one.

Maybe I'm just going insane and I THINK I saw it, because I've been searching for 2 hours and haven't found it yet.

Anyway, if this description reminds you of a post with such code, I would deeply appreciate any links you feel like sharing.

If not, well, I'll just have to pursue another route.


Thanks in advance for your time.
footswitch


edited 2012-04-10: updated topic title

Edited by footswitch, 19 April 2012 - 09:00 PM.






#2 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 06 April 2012 - 09:04 AM

I guess this post is a good start. Using UEZ's program you can embed more custom icons into the script.
  • footswitch likes this

#3 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 09 April 2012 - 09:21 AM

Yup. A good start indeed. Still don't understand even half of it ;)
The embedding technique is pretty awesome and also an eye opener for me. Up until now I was using exclusively icons.

Many thanks. I guess I'll be spending my free time around these UDFs :)

Just a little question, if you don't mind. Can you tell why the checkboxes shift one or two pixels down when the row is selected? This happens regardless of their state (checked or unchecked).
(Windows XP Pro 32-bit, don't know if the behavior persists on other OS)


Thanks again.
footswitch

#4 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 10 April 2012 - 08:30 AM

You're right, I've noticed the one pixel gap before and forgot about it. It seems there's a difference in positioning between XP and Vista+. Not sure what the reason is and the proper handling would be, but these this work-around lines seem to do the job:

Local $iAdjustV = 0 If $__WINVER > 0x0600 Then $iAdjustV = 1 ; $__WINVER defined in WinAPIEx, $__WINVER > 0x0600 means Vista+


Attached File  _LV_Checkboxes.zip   297.76K   117 downloads

#5 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 10 April 2012 - 03:24 PM

Thanks, your fix works nicely.
I ended up setting that as a Global variable on the beginning of the script, since the calculation only needs to occur once.

Right now I'm trying to get this to work together with the Extended Style $LVS_OWNERDRAWFIXED.
It seems like one overrides the other, but I'm still unsure.
A lot of this code is beyond my knowledge so I'm just trying to figure out things as I go.

#6 Zedna

Zedna

    AutoIt rulez!

  • MVPs
  • 8,315 posts

Posted 10 April 2012 - 04:59 PM

For embedding/using icons in compiled EXE script use

#AutoIt3Wrapper_Res_Icon_Add=C:Program FilesAutoIt3Iconsau3.ico #AutoIt3Wrapper_Res_Icon_Add=C:Program FilesAutoIt3Iconssecond_ico.ico


and for loading

_WinAPI_GetModuleHandle("")
_WinAPI_LoadImage() + IMAGE_ICON type as parameter or LoadIcon API function
or you can use GUICtrlSetImage() + @ScriptFullPath

You can look at my Resource to some similar using of resources. Icons are so simple that my Resources UDF is not needed.
http://www.autoitscript.com/forum/topic/51103-resources-udf/

Edited by Zedna, 10 April 2012 - 05:00 PM.

  • footswitch likes this

#7 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 10 April 2012 - 06:04 PM

@Zedna,
#AutoIt3Wrapper_Res_Icon_Add
that's what I've been doing up until now. At this point we can agree that there are several ways to skin this cat.

I really appreciate your help guys, but it seems that it doesn't do what I imagined it would.
I just can't get it to play along with ownerdraw.

I'll post an example script as soon as I can, to demonstrate what I'm talking about.
It's just taking a bit longer than I expected because I'm still cleaning up the code. (plus I need to get all the necessary functions in a single file)

Thanks again.

#8 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 11 April 2012 - 05:21 PM

So I ended up reusing KaFu's example to reproduce the problem:
(you need WinAPIEx.au3 : http://www.autoitscript.com/forum/topic/98712-winapiex-udf/ )

AutoIt         
#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Array.au3> #include <GDIPlus.au3> #include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> ;#include <APIConstants.au3> #include <WinAPIEx.au3> ; from <a href='http://www.autoitscript.com/forum/topic/98712-winapiex-udf/' class='bbc_url' title=''>http://www.autoitscript.com/forum/topic/98712-winapiex-udf/</a> Global Const $ODT_LISTVIEW = 102 Global Const $ODA_DRAWENTIRE = 0x1 ; #################################### ; adjustment of the icon positioning, according to windows version Global $iAdjustV = 0 If $__WINVER > 0x0600 Then $iAdjustV = 1 ; $__WINVER defined in WinAPIEx, $__WINVER > 0x0600 means Vista+ ; #################################### _GDIPlus_Startup() $hGUI = GUICreate("ListView Set Item State", 400, 300) $cButton_CheckAll = GUICtrlCreateButton("Check All", 10, 275, 100, 20) $cButton_UncheckAll = GUICtrlCreateButton("UnCheck All", 120, 275, 100, 20) $cButton_StatesToArray = GUICtrlCreateButton("States to Array", 230, 275, 100, 20) ; comment one of the lines below to reproduce each example (don't leave both uncommented!) ; EXAMPLE 1 (WITH OWNERDRAW): $cListView = GUICtrlCreateListView("", 2, 2, 394, 268, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED, $LVS_SHOWSELALWAYS)) ; EXAMPLE 2 (WITHOUT OWNERDRAW): ;$cListView = GUICtrlCreateListView("", 2, 2, 394, 268, BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS)) $hListView = GUICtrlGetHandle($cListView) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES)) $hIml_Listview = _GUIImageList_Create(16, 16, 5, 3) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Unchecked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Checked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) _GUICtrlListView_SetImageList($hListView, $hIml_Listview, 1) ; Add columns For $i=1 To 3     _GUICtrlListView_AddColumn($hListView, "Column " & $i, 120) Next ; Add items For $row = 1 To 3     _GUICtrlListView_AddItem($hListView, "Row " & $row & ": Col 1", 0)     _GUICtrlListView_AddSubItem($hListView, $row - 1, "Row " & $row & ": Col 2", 1, 0)     _GUICtrlListView_AddSubItem($hListView, $row - 1, "Row " & $row & ": Col 3", 2, 0) Next GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") GUISetState() ; Loop until user exits While 1     Switch GUIGetMsg()         Case $GUI_EVENT_CLOSE             ExitLoop         Case $cButton_CheckAll             _LV_ImgCheckboxes_CheckAll($hListView)         Case $cButton_UncheckAll             _LV_ImgCheckboxes_UncheckAll($hListView)         Case $cButton_StatesToArray             $aLVStates = _LV_ImgCheckboxes_StatesToArray($hListView)             _ArrayDisplay($aLVStates)     EndSwitch WEnd GUIDelete() _GUIImageList_Destroy($hIml_Listview) _GDIPlus_Shutdown() Exit Func _LV_ImgCheckboxes_CheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 1, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_CheckAll Func _LV_ImgCheckboxes_UncheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 0, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_UncheckAll Func _LV_ImgCheckboxes_StatesToArray($hWnd)     Local $iColumns = _GUICtrlListView_GetColumnCount($hWnd)     If $iColumns = 0 Then Return SetError(1)     Local $iItems = _GUICtrlListView_GetItemCount($hWnd)     If $iItems = 0 Then Return SetError(2)     Local $aStates[$iItems][$iColumns]     For $i = 0 To $iItems - 1         For $y = 0 To $iColumns - 1             $aStates[$i][$y] = _GUICtrlListView_GetItemImage($hWnd, $i, $y)         Next     Next     Return $aStates EndFunc   ;==>_LV_ImgCheckboxes_StatesToArray Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)     Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)     Local $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")     Local $nNotifyCode = DllStructGetData($tNMHDR, "Code")     Switch $hWndFrom         Case $hListView             Switch $nNotifyCode                 Case $NM_CUSTOMDRAW                     ; <a href='http://www.autoitscript.com/forum/topic/123757-focushighlight-a-certain-item-in-a-listview/page__view__findpost__p__859598' class='bbc_url' title=''>http://www.autoitscript.com/forum/topic/123757-focushighlight-a-certain-item-in-a-listview/page__view__findpost__p__859598</a>                     ; Mat & Siao                     If Not _GUICtrlListView_GetViewDetails($hWndFrom) Then Return $GUI_RUNDEFMSG ; Not in details mode                     Local $tCustDraw, $iDrawStage, $iItem, $iSubitem, $hDC, $tRect, $iColor1, $iColor2, $iColor3                     $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)                     $iDrawStage = DllStructGetData($tCustDraw, 'dwDrawStage')                     Switch $iDrawStage                         Case $CDDS_PREPAINT                             Return $CDRF_NOTIFYITEMDRAW                         Case $CDDS_ITEMPREPAINT                             Return $CDRF_NOTIFYSUBITEMDRAW                         Case $CDDS_ITEMPOSTPAINT                             ; Not handled                         Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM)                             Local $iItem = DllStructGetData($tCustDraw, 'dwItemSpec')                             Local $iSubitem = DllStructGetData($tCustDraw, 'iSubItem')                             If _GUICtrlListView_GetItemSelected($hWndFrom, $iItem) Then ; Item to draw is selected                                 Local $hDC = _WinAPI_GetDC($hWndFrom)                                 Local $tRect = DllStructCreate($tagRECT)                                 Local $pRect = DllStructGetPtr($tRect)                                 ; We draw the background when we draw the first item.                                 If $iSubitem = 0 Then                                     ; We must send the message as we want to use the struct. _GUICtrlListView_GetSubItemRect returns an array.                                     _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, $pRect)                                     DllStructSetData($tRect, "Left", 0)                                     _WinAPI_FillRect($hDC, DllStructGetPtr($tRect), _WinAPI_GetStockObject(0)) ; NULL_PEN to overwrite default highlighting                                 EndIf                                 DllStructSetData($tRect, "Left", 2)                                 DllStructSetData($tRect, "Top", $iSubitem)                                 _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, DllStructGetPtr($tRect))                                 Local $sText = _GUICtrlListView_GetItemText($hWndFrom, $iItem, $iSubitem)                                 _WinAPI_SetBkMode($hDC, $TRANSPARENT) ; It uses the background drawn for the first item.                                 ; Select the font we want to use                                 _WinAPI_SelectObject($hDC, _SendMessage($hWndFrom, $WM_GETFONT))                                 Local $hIcon = _GUIImageList_GetIcon($hIml_Listview, _GUICtrlListView_GetItemImage($hListView, $iItem, $iSubitem))                                 If $iSubitem = 0 Then                                     _WinAPI_DrawIconEx($hDC, DllStructGetData($tRect, "Left") - 16, DllStructGetData($tRect, "Top") + $iAdjustV, $hIcon, 16, 16)                                     DllStructSetData($tRect, "Left", DllStructGetData($tRect, "Left") + 2)                                 Else                                     _WinAPI_DrawIconEx($hDC, DllStructGetData($tRect, "Left"), DllStructGetData($tRect, "Top") + $iAdjustV, $hIcon, 16, 16)                                     DllStructSetData($tRect, "Left", DllStructGetData($tRect, "Left") + 6 + 18)                                 EndIf                                 _GUIImageList_DestroyIcon($hIcon)                                 _WinAPI_DrawText($hDC, $sText, $tRect, BitOR($DT_VCENTER, $DT_END_ELLIPSIS, $DT_SINGLELINE))                                 _WinAPI_ReleaseDC($hWndFrom, $hDC)                                 Return $CDRF_SKIPDEFAULT ; Don't do default processing                             EndIf                             Return $CDRF_NEWFONT ; Let the system do the drawing for non-selected items                         Case BitOR($CDDS_ITEMPOSTPAINT, $CDDS_SUBITEM)                             ; Not handled                     EndSwitch                 Case $NM_CLICK                     Local $tINFO = DllStructCreate($tagNMITEMACTIVATE, $lParam)                     Local $iItem = DllStructGetData($tINFO, "Index")                     Local $iSubitem = DllStructGetData($tINFO, "SubItem")                     _GUICtrlListView_SetItemImage($hListView, $iItem, Not _GUICtrlListView_GetItemImage($hListView, $iItem, $iSubitem), $iSubitem)             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)     Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC     $tagDRAWITEMSTRUCT = DllStructCreate( _             "uint cType;" & _             "uint cID;" & _             "uint itmID;" & _             "uint itmAction;" & _             "uint itmState;" & _             "hwnd hItm;" & _             "hwnd hDC;" & _             "int itmRect[4];" & _             "dword itmData" _             , $lParam)     If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG     $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")     $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")     $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")     $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")     $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")     $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")     Local $aDefaultVariables[9] = [$tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC]     Switch $cID ; will look for ControlID, not window handle.         Case $cListView             Switch $itmAction                 Case $ODA_DRAWENTIRE                     ConsoleWrite("test"&@CRLF)                     Local $aRowColors[2] = [0xFDFDFD, 0xEEDDBB]                     Local $aRectMargins[4] = [6, -1, 0, 0]                     Local $aTextFormatting[3] = [BitOR($DT_VCENTER, $DT_SINGLELINE), _                     BitOR($DT_VCENTER, $DT_SINGLELINE), _                     BitOR($DT_VCENTER, $DT_SINGLELINE)]                     __WM_DRAWITEM_ListView($hListView, $aDefaultVariables, $aRowColors, $aRectMargins, $aTextFormatting)             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_DRAWITEM Func __WM_DRAWITEM_ListView(ByRef $hListView, ByRef $aDefaultVariables, ByRef $aRowColors, ByRef $aRectMargins, ByRef $aTextFormatting)     Local $iSubItemCount = _GUICtrlListView_GetColumnCount($hListView)     If UBound($aTextFormatting) < $iSubItemCount Then         ConsoleWrite("!> Error: invalid parameters in __WM_DRAWITEM_ListView()"&@CRLF)         Return     EndIf     Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC     $tagDRAWITEMSTRUCT = $aDefaultVariables[0]     $iBrushColor = $aDefaultVariables[1]     $cID = $aDefaultVariables[2]     $itmID = $aDefaultVariables[3]     $itmAction = $aDefaultVariables[4]     $itmState = $aDefaultVariables[5]     $hItm = $aDefaultVariables[6]     $hDC = $aDefaultVariables[7]     If _GUICtrlListView_GetItemSelected($hListView, $itmID) Then         $iBrushColor = $aRowColors[1]     Else         $iBrushColor = $aRowColors[0]     EndIf     ; create a brush with the desired color:     Local $aBrush = DllCall("gdi32.dll", "hwnd", "CreateSolidBrush", "int", $iBrushColor)     ; get the rectangle for the whole row and fill it:     Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)     DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 0, 1) ; +0 is the left margin     _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])     ; draw the text in each subitem     For $i = 0 To $iSubItemCount - 1         ; get subitem text:         Local $iSubItmText = _GUICtrlListView_GetItemText($hListView, $itmID, $i)         ; get subitem coordinates for drawing its respective text:         Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hListView, $itmID, $i)         ; the function above accepts not only subitems (one-based index), but also main item (index=0)         ; pass the coordinates to a DLL struct:         Local $iSubItmRect = DllStructCreate("int[4]")         DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + $aRectMargins[0], 1) ; left margin         DllStructSetData($iSubItmRect, 1, $aSubItmRect[1] + $aRectMargins[1], 2) ; upper margin         DllStructSetData($iSubItmRect, 1, $aSubItmRect[2] + $aRectMargins[2], 3) ; right margin         DllStructSetData($iSubItmRect, 1, $aSubItmRect[3] + $aRectMargins[3], 4) ; bottom margin         Local $tRect = DllStructGetPtr($iSubItmRect)         If $aTextFormatting[$i] = -1 Then             ; do nothing (don't draw)         Else             _WinAPI_DrawText($hDC, $iSubItmText, $tRect, $aTextFormatting[$i])         EndIf     Next EndFunc ; Based on File to Base64 String Code Generator ; by UEZ ; <a href='http://www.autoitscript.com/forum/topic/134350-file-to-base64-string-code-generator-v103-build-2011-11-21/' class='bbc_url' title=''>http://www.autoitscript.com/forum/topic/134350-file-to-base64-string-code-generator-v103-build-2011-11-21/</a> ;====================================================================================== ; Function Name:        Load_BMP_From_Mem ; Description:        Loads an image which is saved as a binary string and converts it to a bitmap or hbitmap ; ; Parameters:          $bImage:    the binary string which contains any valid image which is supported by GDI+ ; Optional:          $hHBITMAP:  if false a bitmap will be created, if true a hbitmap will be created ; ; Remark:              hbitmap format is used generally for GUI internal images, $bitmap is more a GDI+ image format ;                      Don't forget _GDIPlus_Startup() and _GDIPlus_Shutdown() ; ; Requirement(s):      GDIPlus.au3, Memory.au3 and _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Return Value(s):    Success: handle to bitmap (GDI+ bitmap format) or hbitmap (WinAPI bitmap format), ;                      Error: 0 ; Error codes:        1: $bImage is not a binary string ;                      2: unable to create stream on HGlobal ;                      3: unable to create bitmap from stream ; ; Author(s):            UEZ ; Additional Code:    thanks to progandy for the MemGlobalAlloc and tVARIANT lines and ;                      Yashied for _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Version:            v0.97 Build 2012-01-04 Beta ;======================================================================================= Func _Load_BMP_From_Mem($bImage, $hHBITMAP = False)     If Not IsBinary($bImage) Then Return SetError(1, 0, 0)     Local $aResult     Local Const $memBitmap = Binary($bImage) ;load image  saved in variable (memory) and convert it to binary     Local Const $len = BinaryLen($memBitmap) ;get length of image     Local Const $hData = _MemGlobalAlloc($len, $GMEM_MOVEABLE) ;allocates movable memory  ($GMEM_MOVEABLE = 0x0002)     Local Const $pData = _MemGlobalLock($hData) ;translate the handle into a pointer     Local $tMem = DllStructCreate("byte[" & $len & "]", $pData) ;create struct     DllStructSetData($tMem, 1, $memBitmap) ;fill struct with image data     _MemGlobalUnlock($hData) ;decrements the lock count  associated with a memory object that was allocated with GMEM_MOVEABLE     $aResult = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "handle", $pData, "int", True, "ptr*", 0) ;Creates a stream object that uses an HGLOBAL memory handle to store the stream contents     If @error Then SetError(2, 0, 0)     Local Const $hStream = $aResult[3]     $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromStream", "ptr", $hStream, "int*", 0) ;Creates a Bitmap object based on an IStream COM interface     If @error Then SetError(3, 0, 0)     Local Const $hBitmap = $aResult[2]     Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr")     DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, _             "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;release memory from $hStream to avoid memory leak     $tMem = 0     $tVARIANT = 0     If $hHBITMAP Then         Local Const $hHBmp = _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)         _GDIPlus_BitmapDispose($hBitmap)         Return $hHBmp     EndIf     Return $hBitmap EndFunc   ;==>_Load_BMP_From_Mem Func _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)     Local $tBIHDR, $Ret, $tData, $pBits, $hResult = 0     $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)     If (@error) Or ($Ret[0]) Then Return 0     $tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Ret[2], $Ret[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)     $pBits = DllStructGetData($tData, 'Scan0')     If Not $pBits Then Return 0     $tBIHDR = DllStructCreate('dword;long;long;ushort;ushort;dword;dword;long;long;dword;dword')     DllStructSetData($tBIHDR, 1, DllStructGetSize($tBIHDR))     DllStructSetData($tBIHDR, 2, $Ret[2])     DllStructSetData($tBIHDR, 3, $Ret[3])     DllStructSetData($tBIHDR, 4, 1)     DllStructSetData($tBIHDR, 5, 32)     DllStructSetData($tBIHDR, 6, 0)     $hResult = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBIHDR), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'dword', 0)     If (Not @error) And ($hResult[0]) Then         DllCall('gdi32.dll', 'dword', 'SetBitmapBits', 'ptr', $hResult[0], 'dword', $Ret[2] * $Ret[3] * 4, 'ptr', DllStructGetData($tData, 'Scan0'))         $hResult = $hResult[0]     Else         $hResult = 0     EndIf     _GDIPlus_BitmapUnlockBits($hBitmap, $tData)     Return $hResult EndFunc   ;==>_GDIPlus_BitmapCreateDIBFromBitmap Func _Decompress_Binary_String_to_Bitmap($Base64String)     $Base64String = Binary($Base64String)     Local $iSize_Source = BinaryLen($Base64String)     Local $pBuffer_Source = _WinAPI_CreateBuffer($iSize_Source)     DllStructSetData(DllStructCreate('byte[' & $iSize_Source & ']', $pBuffer_Source), 1, $Base64String)     Local $pBuffer_Decompress = _WinAPI_CreateBuffer(8388608)     Local $Size_Decompressed = _WinAPI_DecompressBuffer($pBuffer_Decompress, 8388608, $pBuffer_Source, $iSize_Source)     Local $b_Result = Binary(DllStructGetData(DllStructCreate('byte[' & $Size_Decompressed & ']', $pBuffer_Decompress), 1))     _WinAPI_FreeMemory($pBuffer_Source)     _WinAPI_FreeMemory($pBuffer_Decompress)     Return $b_Result EndFunc   ;==>_Decompress_Binary_String_to_Bitmap Func _Icon_Image_Checkbox_Unchecked()     Local $Base64String     $Base64String &= '7rBIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAANfc3ADZ3t4AANvg4ADe4uIAAOLl5QDl6OgAAOns7ADs7+8AAO/x8QDx8/MAAPT19QD29/cAAPj5+QD6+/sAAPz9/QD+/v7wAP///xNc/wB/AD8A/z8APwA/AD8APwA/AD8ACAAb4HYLAAEJAOEBCgsMAA0ODxAREhISbeIBCQcC4gEIBwLiAQfbBwLiAQYHAuIBBQcC4gG2BAcC4gEDBwLiAQIHAv/jAQcC5AEGAuIB7BceAOCfHgN/AG0A4QZhAA=='     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Unchecked Func _Icon_Image_Checkbox_Checked()     Local $Base64String     $Base64String &= 'z7BIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAAISEhADe3t5AAN7n5wDnAQbvCO8A7wEG9/cA9/EABv///xN4/wE/AD8A/z8APwA/AD8AHwAMAOB6CwAGAQkA4QEHCAkJCR4KAgDjAQcC5AEHCAKDAwLiAQYHBwICAwI54gEFBsABAwLjAQUCxgIkBOIBBAUCRQbjAVgEBQUCAuQBAwUCCPPkAQUCBwjkAQYC4gHsF3seAOCfA38AbQDhBmEA'     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Checked Func _Base64Decode($input_string)     Local $struct = DllStructCreate("int")     Local $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", 0, "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(1, 0, "")     Local $a = DllStructCreate("byte[" & DllStructGetData($struct, 1) & "]")     $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", DllStructGetPtr($a), "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(2, 0, "")     Return DllStructGetData($a, 1) EndFunc   ;==>_Base64Decode



As you can see, I can only display one of the effects: either OWNERDRAW or the other 'dwDrawStage' method.
When I hoped it would be possible to blend them together.

Have you guys ever tried something like this?

#9 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 11 April 2012 - 06:18 PM

Looks good on Win7 ;)...

AutoIt         
#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Array.au3> #include <GDIPlus.au3> #include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> ;#include <APIConstants.au3> #include <WinAPIEx.au3> ; from <a href='http://www.autoitscript.com/forum/topic/98712-winapiex-udf/' class='bbc_url' title='' rel='norewrite'>http://www.autoitscript.com/forum/topic/98712-winapiex-udf/</a> Global Const $ODT_LISTVIEW = 102 Global Const $ODA_DRAWENTIRE = 0x1 ; #################################### ; adjustment of the icon positioning, according to windows version Global $iAdjustV = 0 If $__WINVER > 0x0600 Then $iAdjustV = 1 ; $__WINVER defined in WinAPIEx, $__WINVER > 0x0600 means Vista+ ; #################################### _GDIPlus_Startup() $hGUI = GUICreate("ListView Set Item State", 400, 300) $cButton_CheckAll = GUICtrlCreateButton("Check All", 10, 275, 100, 20) $cButton_UncheckAll = GUICtrlCreateButton("UnCheck All", 120, 275, 100, 20) $cButton_StatesToArray = GUICtrlCreateButton("States to Array", 230, 275, 100, 20) ; comment one of the lines below to reproduce each example (don't leave both uncommented!) ; EXAMPLE 1 (WITH OWNERDRAW): $cListView = GUICtrlCreateListView("", 2, 2, 394, 268, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED, $LVS_SHOWSELALWAYS)) ; EXAMPLE 2 (WITHOUT OWNERDRAW): ;$cListView = GUICtrlCreateListView("", 2, 2, 394, 268, BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS)) $hListView = GUICtrlGetHandle($cListView) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES)) $hIml_Listview = _GUIImageList_Create(16, 16, 5, 3) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Unchecked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Checked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) _GUICtrlListView_SetImageList($hListView, $hIml_Listview, 1) ; Add columns For $i = 1 To 3     _GUICtrlListView_AddColumn($hListView, "Column " & $i, 120) Next ; Add items For $row = 1 To 3     _GUICtrlListView_AddItem($hListView, "Row " & $row & ": Col 1", 0)     _GUICtrlListView_AddSubItem($hListView, $row - 1, "Row " & $row & ": Col 2", 1, 0)     _GUICtrlListView_AddSubItem($hListView, $row - 1, "Row " & $row & ": Col 3", 2, 0) Next GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") GUISetState() ; Loop until user exits While 1     Switch GUIGetMsg()         Case $GUI_EVENT_CLOSE             ExitLoop         Case $cButton_CheckAll             _LV_ImgCheckboxes_CheckAll($hListView)         Case $cButton_UncheckAll             _LV_ImgCheckboxes_UncheckAll($hListView)         Case $cButton_StatesToArray             $aLVStates = _LV_ImgCheckboxes_StatesToArray($hListView)             _ArrayDisplay($aLVStates)     EndSwitch WEnd GUIDelete() _GUIImageList_Destroy($hIml_Listview) _GDIPlus_Shutdown() Exit Func _LV_ImgCheckboxes_CheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 1, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_CheckAll Func _LV_ImgCheckboxes_UncheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 0, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_UncheckAll Func _LV_ImgCheckboxes_StatesToArray($hWnd)     Local $iColumns = _GUICtrlListView_GetColumnCount($hWnd)     If $iColumns = 0 Then Return SetError(1)     Local $iItems = _GUICtrlListView_GetItemCount($hWnd)     If $iItems = 0 Then Return SetError(2)     Local $aStates[$iItems][$iColumns]     For $i = 0 To $iItems - 1         For $y = 0 To $iColumns - 1             $aStates[$i][$y] = _GUICtrlListView_GetItemImage($hWnd, $i, $y)         Next     Next     Return $aStates EndFunc   ;==>_LV_ImgCheckboxes_StatesToArray Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)     Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)     Local $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")     Local $nNotifyCode = DllStructGetData($tNMHDR, "Code")     Switch $hWndFrom         Case $hListView             Switch $nNotifyCode                 #cs                     Case $NM_CUSTOMDRAW                     ConsoleWrite(TimerInit() & @TAB & "$NM_CUSTOMDRAW" & @CRLF)                     ; <a href='http://www.autoitscript.com/forum/topic/...listview/page__view__findpost_' class='bbc_url' title='' rel='norewrite'>http://www.autoitscript.com/forum/topic/...listview/page__view__findpost_</a>                     ; Mat & Siao                                         If Not _GUICtrlListView_GetViewDetails($hWndFrom) Then Return $GUI_RUNDEFMSG ; Not in details mode                                         Local $tCustDraw, $iDrawStage, $iItem, $iSubitem, $hDC, $tRect, $iColor1, $iColor2, $iColor3                                         $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)                     $iDrawStage = DllStructGetData($tCustDraw, 'dwDrawStage')                                         Switch $iDrawStage                     Case $CDDS_PREPAINT                     Return $CDRF_NOTIFYITEMDRAW                     Case $CDDS_ITEMPREPAINT                     Return $CDRF_NOTIFYSUBITEMDRAW                     Case $CDDS_ITEMPOSTPAINT                     ; Not handled                     Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM)                                         Local $iItem = DllStructGetData($tCustDraw, 'dwItemSpec')                     Local $iSubitem = DllStructGetData($tCustDraw, 'iSubItem')                                         If _GUICtrlListView_GetItemSelected($hWndFrom, $iItem) Then ; Item to draw is selected                     Local $hDC = _WinAPI_GetDC($hWndFrom)                     Local $tRect = DllStructCreate($tagRECT)                     Local $pRect = DllStructGetPtr($tRect)                                         ; We draw the background when we draw the first item.                     If $iSubitem = 0 Then                     ; We must send the message as we want to use the struct. _GUICtrlListView_GetSubItemRect returns an array.                     _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, $pRect)                     DllStructSetData($tRect, "Left", 0)                     _WinAPI_FillRect($hDC, DllStructGetPtr($tRect), _WinAPI_GetStockObject(0)) ; NULL_PEN to overwrite default highlighting                     EndIf                                         DllStructSetData($tRect, "Left", 2)                     DllStructSetData($tRect, "Top", $iSubitem)                     _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, DllStructGetPtr($tRect))                     Local $sText = _GUICtrlListView_GetItemText($hWndFrom, $iItem, $iSubitem)                     _WinAPI_SetBkMode($hDC, $TRANSPARENT) ; It uses the background drawn for the first item.                                         ; Select the font we want to use                     _WinAPI_SelectObject($hDC, _SendMessage($hWndFrom, $WM_GETFONT))                                         Local $hIcon = _GUIImageList_GetIcon($hIml_Listview, _GUICtrlListView_GetItemImage($hListView, $iItem, $iSubitem))                                         If $iSubitem = 0 Then                     _WinAPI_DrawIconEx($hDC, DllStructGetData($tRect, "Left") - 16, DllStructGetData($tRect, "Top") + $iAdjustV, $hIcon, 16, 16)                     DllStructSetData($tRect, "Left", DllStructGetData($tRect, "Left") + 2)                     Else                     _WinAPI_DrawIconEx($hDC, DllStructGetData($tRect, "Left"), DllStructGetData($tRect, "Top") + $iAdjustV, $hIcon, 16, 16)                     DllStructSetData($tRect, "Left", DllStructGetData($tRect, "Left") + 6 + 18)                     EndIf                                         _GUIImageList_DestroyIcon($hIcon)                     _WinAPI_DrawText($hDC, $sText, $tRect, BitOR($DT_VCENTER, $DT_END_ELLIPSIS, $DT_SINGLELINE))                                         _WinAPI_ReleaseDC($hWndFrom, $hDC)                                         Return $CDRF_SKIPDEFAULT ; Don't do default processing                                         EndIf                                         Return $CDRF_NEWFONT ; Let the system do the drawing for non-selected items                     Case BitOR($CDDS_ITEMPOSTPAINT, $CDDS_SUBITEM)                     ; Not handled                     EndSwitch                 #ce                 Case $NM_CLICK                     Local $tINFO = DllStructCreate($tagNMITEMACTIVATE, $lParam)                     Local $iItem = DllStructGetData($tINFO, "Index")                     Local $iSubitem = DllStructGetData($tINFO, "SubItem")                     _GUICtrlListView_SetItemImage($hListView, $iItem, Not _GUICtrlListView_GetItemImage($hListView, $iItem, $iSubitem), $iSubitem)             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)     Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC     ;ConsoleWrite(TimerInit() & @TAB & "WM_DRAWITEM" & @CRLF)     $tagDRAWITEMSTRUCT = DllStructCreate( _             "uint cType;" & _             "uint cID;" & _             "uint itmID;" & _             "uint itmAction;" & _             "uint itmState;" & _             "hwnd hItm;" & _             "hwnd hDC;" & _             "int itmRect[4];" & _             "dword itmData" _             , $lParam)     If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG     $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")     $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")     $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")     $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")     $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")     $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")     Local $aDefaultVariables[9] = [$tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC]     Switch $cID ; will look for ControlID, not window handle.         Case $cListView             Switch $itmAction                 Case $ODA_DRAWENTIRE                     ConsoleWrite("test" & @CRLF)                     Local $aRowColors[2] = [0xFDFDFD, 0xEEDDBB]                     Local $aRectMargins[4] = [6, -1, 0, 0]                     Local $aTextFormatting[3] = [BitOR($DT_VCENTER, $DT_SINGLELINE), _                             BitOR($DT_VCENTER, $DT_SINGLELINE), _                             BitOR($DT_VCENTER, $DT_SINGLELINE)]                     __WM_DRAWITEM_ListView($hListView, $aDefaultVariables, $aRowColors, $aRectMargins, $aTextFormatting)             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_DRAWITEM Func __WM_DRAWITEM_ListView(ByRef $hListView, ByRef $aDefaultVariables, ByRef $aRowColors, ByRef $aRectMargins, ByRef $aTextFormatting)     Local $iSubItemCount = _GUICtrlListView_GetColumnCount($hListView)     If UBound($aTextFormatting) < $iSubItemCount Then         ConsoleWrite("!> Error: invalid parameters in __WM_DRAWITEM_ListView()" & @CRLF)         Return     EndIf     Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC     $tagDRAWITEMSTRUCT = $aDefaultVariables[0]     $iBrushColor = $aDefaultVariables[1]     $cID = $aDefaultVariables[2]     $itmID = $aDefaultVariables[3]     $itmAction = $aDefaultVariables[4]     $itmState = $aDefaultVariables[5]     $hItm = $aDefaultVariables[6]     $hDC = $aDefaultVariables[7]     If _GUICtrlListView_GetItemSelected($hListView, $itmID) Then         $iBrushColor = $aRowColors[1]     Else         $iBrushColor = $aRowColors[0]     EndIf     ; create a brush with the desired color:     Local $aBrush = DllCall("gdi32.dll", "hwnd", "CreateSolidBrush", "int", $iBrushColor)     ; get the rectangle for the whole row and fill it:     Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)     DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 0, 1) ; +0 is the left margin     _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])     ; draw the text in each subitem     For $i = 0 To $iSubItemCount - 1         ; get subitem text:         Local $iSubItmText = _GUICtrlListView_GetItemText($hListView, $itmID, $i)         ; get subitem coordinates for drawing its respective text:         Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hListView, $itmID, $i)         ; the function above accepts not only subitems (one-based index), but also main item (index=0)         ; pass the coordinates to a DLL struct:         Local $iSubItmRect = DllStructCreate("int Left;int Top;int Right;int Bottom")         DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + $aRectMargins[0]) ; left margin         DllStructSetData($iSubItmRect, 2, $aSubItmRect[1] + $aRectMargins[1]) ; upper margin         DllStructSetData($iSubItmRect, 3, $aSubItmRect[2] + $aRectMargins[2]) ; right margin         DllStructSetData($iSubItmRect, 4, $aSubItmRect[3] + $aRectMargins[3]) ; bottom margin         Local $tRect = DllStructGetPtr($iSubItmRect)         Local $hIcon = _GUIImageList_GetIcon($hIml_Listview, _GUICtrlListView_GetItemImage($hListView, $itmID, $i))         If $i = 0 Then             DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 12)             _WinAPI_DrawIconEx($hDC, DllStructGetData($iSubItmRect, "Left") - 16, DllStructGetData($iSubItmRect, "Top") + $iAdjustV, $hIcon, 16, 16)             DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 2)         Else             _WinAPI_DrawIconEx($hDC, DllStructGetData($iSubItmRect, "Left"), DllStructGetData($iSubItmRect, "Top") + $iAdjustV, $hIcon, 16, 16)             DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 6 + 18)         EndIf         _GUIImageList_DestroyIcon($hIcon)         If $aTextFormatting[$i] = -1 Then             ; do nothing (don't draw)         Else             _WinAPI_DrawText($hDC, $iSubItmText, $tRect, $aTextFormatting[$i])         EndIf     Next EndFunc   ;==>__WM_DRAWITEM_ListView ; Based on File to Base64 String Code Generator ; by UEZ ; <a href='http://www.autoitscript.com/forum/topic/...ng-code-generator-v103-build-2' class='bbc_url' title='' rel='norewrite'>http://www.autoitscript.com/forum/topic/...ng-code-generator-v103-build-2</a> ;====================================================================================== ; Function Name:        Load_BMP_From_Mem ; Description:      Loads an image which is saved as a binary string and converts it to a bitmap or hbitmap ; ; Parameters:         $bImage:    the binary string which contains any valid image which is supported by GDI+ ; Optional:       $hHBITMAP:  if false a bitmap will be created, if true a hbitmap will be created ; ; Remark:             hbitmap format is used generally for GUI internal images, $bitmap is more a GDI+ image format ;                     Don't forget _GDIPlus_Startup() and _GDIPlus_Shutdown() ; ; Requirement(s):     GDIPlus.au3, Memory.au3 and _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Return Value(s):    Success: handle to bitmap (GDI+ bitmap format) or hbitmap (WinAPI bitmap format), ;                     Error: 0 ; Error codes:      1: $bImage is not a binary string ;                     2: unable to create stream on HGlobal ;                     3: unable to create bitmap from stream ; ; Author(s):            UEZ ; Additional Code:    thanks to progandy for the MemGlobalAlloc and tVARIANT lines and ;                     Yashied for _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Version:          v0.97 Build 2012-01-04 Beta ;======================================================================================= Func _Load_BMP_From_Mem($bImage, $hHBITMAP = False)     If Not IsBinary($bImage) Then Return SetError(1, 0, 0)     Local $aResult     Local Const $memBitmap = Binary($bImage) ;load image  saved in variable (memory) and convert it to binary     Local Const $len = BinaryLen($memBitmap) ;get length of image     Local Const $hData = _MemGlobalAlloc($len, $GMEM_MOVEABLE) ;allocates movable memory  ($GMEM_MOVEABLE = 0x0002)     Local Const $pData = _MemGlobalLock($hData) ;translate the handle into a pointer     Local $tMem = DllStructCreate("byte[" & $len & "]", $pData) ;create struct     DllStructSetData($tMem, 1, $memBitmap) ;fill struct with image data     _MemGlobalUnlock($hData) ;decrements the lock count  associated with a memory object that was allocated with GMEM_MOVEABLE     $aResult = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "handle", $pData, "int", True, "ptr*", 0) ;Creates a stream object that uses an HGLOBAL memory handle to store the stream contents     If @error Then SetError(2, 0, 0)     Local Const $hStream = $aResult[3]     $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromStream", "ptr", $hStream, "int*", 0) ;Creates a Bitmap object based on an IStream COM interface     If @error Then SetError(3, 0, 0)     Local Const $hBitmap = $aResult[2]     Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr")     DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, _             "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;release memory from $hStream to avoid memory leak     $tMem = 0     $tVARIANT = 0     If $hHBITMAP Then         Local Const $hHBmp = _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)         _GDIPlus_BitmapDispose($hBitmap)         Return $hHBmp     EndIf     Return $hBitmap EndFunc   ;==>_Load_BMP_From_Mem Func _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)     Local $tBIHDR, $Ret, $tData, $pBits, $hResult = 0     $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)     If (@error) Or ($Ret[0]) Then Return 0     $tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Ret[2], $Ret[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)     $pBits = DllStructGetData($tData, 'Scan0')     If Not $pBits Then Return 0     $tBIHDR = DllStructCreate('dword;long;long;ushort;ushort;dword;dword;long;long;dword;dword')     DllStructSetData($tBIHDR, 1, DllStructGetSize($tBIHDR))     DllStructSetData($tBIHDR, 2, $Ret[2])     DllStructSetData($tBIHDR, 3, $Ret[3])     DllStructSetData($tBIHDR, 4, 1)     DllStructSetData($tBIHDR, 5, 32)     DllStructSetData($tBIHDR, 6, 0)     $hResult = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBIHDR), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'dword', 0)     If (Not @error) And ($hResult[0]) Then         DllCall('gdi32.dll', 'dword', 'SetBitmapBits', 'ptr', $hResult[0], 'dword', $Ret[2] * $Ret[3] * 4, 'ptr', DllStructGetData($tData, 'Scan0'))         $hResult = $hResult[0]     Else         $hResult = 0     EndIf     _GDIPlus_BitmapUnlockBits($hBitmap, $tData)     Return $hResult EndFunc   ;==>_GDIPlus_BitmapCreateDIBFromBitmap Func _Decompress_Binary_String_to_Bitmap($Base64String)     $Base64String = Binary($Base64String)     Local $iSize_Source = BinaryLen($Base64String)     Local $pBuffer_Source = _WinAPI_CreateBuffer($iSize_Source)     DllStructSetData(DllStructCreate('byte[' & $iSize_Source & ']', $pBuffer_Source), 1, $Base64String)     Local $pBuffer_Decompress = _WinAPI_CreateBuffer(8388608)     Local $Size_Decompressed = _WinAPI_DecompressBuffer($pBuffer_Decompress, 8388608, $pBuffer_Source, $iSize_Source)     Local $b_Result = Binary(DllStructGetData(DllStructCreate('byte[' & $Size_Decompressed & ']', $pBuffer_Decompress), 1))     _WinAPI_FreeMemory($pBuffer_Source)     _WinAPI_FreeMemory($pBuffer_Decompress)     Return $b_Result EndFunc   ;==>_Decompress_Binary_String_to_Bitmap Func _Icon_Image_Checkbox_Unchecked()     Local $Base64String     $Base64String &= '7rBIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAANfc3ADZ3t4AANvg4ADe4uIAAOLl5QDl6OgAAOns7ADs7+8AAO/x8QDx8/MAAPT19QD29/cAAPj5+QD6+/sAAPz9/QD+/v7wAP///xNc/wB/AD8A/z8APwA/AD8APwA/AD8ACAAb4HYLAAEJAOEBCgsMAA0ODxAREhISbeIBCQcC4gEIBwLiAQfbBwLiAQYHAuIBBQcC4gG2BAcC4gEDBwLiAQIHAv/jAQcC5AEGAuIB7BceAOCfHgN/AG0A4QZhAA=='     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Unchecked Func _Icon_Image_Checkbox_Checked()     Local $Base64String     $Base64String &= 'z7BIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAAISEhADe3t5AAN7n5wDnAQbvCO8A7wEG9/cA9/EABv///xN4/wE/AD8A/z8APwA/AD8AHwAMAOB6CwAGAQkA4QEHCAkJCR4KAgDjAQcC5AEHCAKDAwLiAQYHBwICAwI54gEFBsABAwLjAQUCxgIkBOIBBAUCRQbjAVgEBQUCAuQBAwUCCPPkAQUCBwjkAQYC4gHsF3seAOCfA38AbQDhBmEA'     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Checked Func _Base64Decode($input_string)     Local $struct = DllStructCreate("int")     Local $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", 0, "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(1, 0, "")     Local $a = DllStructCreate("byte[" & DllStructGetData($struct, 1) & "]")     $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", DllStructGetPtr($a), "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(2, 0, "")     Return DllStructGetData($a, 1) EndFunc   ;==>_Base64Decode


Edit: Upsa, wrong include path for WinAPIEx...

Edited by KaFu, 11 April 2012 - 06:19 PM.

  • footswitch likes this

#10 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 12 April 2012 - 09:12 AM

OOOOhhhhh...
;)

Thanks a bunch.
I think I'm starting to get it now :)

#11 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 13 April 2012 - 08:17 AM

You're welcome, new terrain for me too and I've learned something along the road ;)!

#12 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 13 April 2012 - 07:01 PM

Glad to know! So... do you feel like extending its functionality even more? ;)
Here are a couple of things I wasn't expecting.
----------
A )
I'm using $WM_MEASUREITEM to set the row height.
But _GUICtrlListView_SetImageList() somehow breaks this.

If I don't use _GUICtrlListView_SetImageList() then the rows have the desired height, and the images show up fine, but the ones in the first column need to be forcibly drawn when clicked. The first column behaves differently than the other subitems in many functions, so I decided to "hide" it (size=0), thus solving all my problems with it.

So, is it wrong not to use _GUICtrlListView_SetImageList()?

----------
B )
In the example below I'm showing two ways of freezing the script when using $LVS_EX_SUBITEMIMAGES.

- One of them is a consequence of using _GUICtrlListView_AddArray() to populate. It must be a function that doesn't perform the same steps as _GUICtrlListView_Add[Sub]Item(). Also it won't draw icons unless you click the respective subitem.
- The other is when you don't populate the rows entirely, that is, if you skip a subitem.

I'm quite stuck with this at this point.

AutoIt         
#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Array.au3> #include <GDIPlus.au3> #include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> ;#include <APIConstants.au3> #include <WinAPIEx.au3> ; from http://www.autoitscript.com/forum/topic/98712-winapiex-udf/ Global Const $ODT_LISTVIEW = 102 Global Const $ODA_DRAWENTIRE = 0x1 ; #################################### ; adjustment of the icon positioning, according to windows version Global $iAdjustV = 0 If $__WINVER > 0x0600 Then $iAdjustV = 1 ; $__WINVER defined in WinAPIEx, $__WINVER > 0x0600 means Vista+ ; #################################### ; WM_MEASUREITEM allows setting the row height Global $iListView_row_height = 50 GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM") ; place before listview creation - message sent once for each ownerdrawn control created ;GUIRegisterMsg($WM_MEASUREITEM, "") ; call this after last ownerdrawn listview created ; --------------------------------------------------- _GDIPlus_Startup() $hGUI = GUICreate("ListView Set Item State", 700, 300) $cButton_CheckAll = GUICtrlCreateButton("Check All", 10, 275, 100, 20) $cButton_UncheckAll = GUICtrlCreateButton("UnCheck All", 120, 275, 100, 20) $cButton_StatesToArray = GUICtrlCreateButton("States to Array", 230, 275, 100, 20) ; listview 1 ----------------------------------------------- $iListView_row_height = 25 $cListView = GUICtrlCreateListView("", 2, 2, 394, 268, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED, $LVS_SHOWSELALWAYS, $LVS_SINGLESEL)) GUICtrlSetFont(-1, 11, 400, 0, "Calibri", 5) $hListView = GUICtrlGetHandle($cListView) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $LVS_EX_SUBITEMIMAGES)) $hIml_Listview = _GUIImageList_Create(16, 16, 5, 3) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Unchecked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Checked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) ; ########################################################## ; this "breaks" WM_MEASUREITEM ;_GUICtrlListView_SetImageList($hListView, $hIml_Listview, 1) ; why do we need this anyway? ; ########################################################## ; Add columns _GUICtrlListView_AddColumn($hListView, " ", 0) For $i = 1 To 3     _GUICtrlListView_AddColumn($hListView, "Column " & $i, 100) Next Local $aItems[30][4] For $row = 1 To 30 $aItems[$row-1][0] = "this won't show up" $aItems[$row-1][1] = "Row " & $row & ": Col 1" $aItems[$row-1][2] = "Row " & $row & ": Col 2" $aItems[$row-1][3] = "Row " & $row & ": Col 3" Next ; if you add items via _GUICtrlListView_AddArray(), the drawing will become unstable. ; also, the checkboxes don't appear unless you click their respective subitem. _GUICtrlListView_DeleteAllItems($hListView) _GUICtrlListView_AddArray($hListView, $aItems) ; ----------------------------------------------------------- ; listview 2 ----------------------------------------------- $iListView_row_height = 40 $cListView_2 = GUICtrlCreateListView("", 400, 2, 298, 268, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED, $LVS_SHOWSELALWAYS)) GUICtrlSetFont(-1, 11, 400, 0, "Calibri", 5) $hListView_2 = GUICtrlGetHandle($cListView_2) _GUICtrlListView_SetExtendedListViewStyle($hListView_2, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES)) ; Add columns For $i = 1 To 3     _GUICtrlListView_AddColumn($hListView_2, "2 - Column " & $i, 90) Next ; Add items For $row = 1 To 20     _GUICtrlListView_AddItem($hListView_2, "Row " & $row & ": Col 0", 0)     _GUICtrlListView_AddSubItem($hListView_2, $row - 1, "Row " & $row & ": Col 1", 1, 0)     If $row <> 3 Then   _GUICtrlListView_AddSubItem($hListView_2, $row - 1, "Row " & $row & ": Col 2", 2, 0) Else   ; if you comment the line below and click+drag to resize this ListView's columns, the drawing will become unstable   ;_GUICtrlListView_AddSubItem($hListView_2, $row - 1, "", 2, 0) EndIf Next ; ----------------------------------------------------------- GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") GUISetState() ; Loop until user exits While 1     Switch GUIGetMsg()         Case $GUI_EVENT_CLOSE             ExitLoop         Case $cButton_CheckAll             _LV_ImgCheckboxes_CheckAll($hListView)         Case $cButton_UncheckAll             _LV_ImgCheckboxes_UncheckAll($hListView)         Case $cButton_StatesToArray             $aLVStates = _LV_ImgCheckboxes_StatesToArray($hListView)             _ArrayDisplay($aLVStates)     EndSwitch WEnd GUIDelete() _GUIImageList_Destroy($hIml_Listview) _GDIPlus_Shutdown() Exit Func _LV_ImgCheckboxes_CheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 1, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_CheckAll Func _LV_ImgCheckboxes_UncheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 0, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_UncheckAll Func _LV_ImgCheckboxes_StatesToArray($hWnd)     Local $iColumns = _GUICtrlListView_GetColumnCount($hWnd)     If $iColumns = 0 Then Return SetError(1)     Local $iItems = _GUICtrlListView_GetItemCount($hWnd)     If $iItems = 0 Then Return SetError(2)     Local $aStates[$iItems][$iColumns]     For $i = 0 To $iItems - 1         For $y = 0 To $iColumns - 1             $aStates[$i][$y] = _GUICtrlListView_GetItemImage($hWnd, $i, $y)         Next     Next     Return $aStates EndFunc   ;==>_LV_ImgCheckboxes_StatesToArray Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)     Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)     Local $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")     Local $nNotifyCode = DllStructGetData($tNMHDR, "Code")     Switch $hWndFrom         Case $hListView             Switch $nNotifyCode                 Case $NM_CLICK                     Local $tINFO = DllStructCreate($tagNMITEMACTIVATE, $lParam)                     Local $iItem = DllStructGetData($tINFO, "Index")                     Local $iSubitem = DllStructGetData($tINFO, "SubItem")                     If $iSubitem == 2 And StringLen(_GUICtrlListView_GetItemText($hListView, $iItem, $iSubitem)) > 0 Then       ;ConsoleWrite("painting row "&$iItem+1&"   col "&$iSubitem+1&@CRLF)       _GUICtrlListView_SetItemImage($hListView, $iItem, Not _GUICtrlListView_GetItemImage($hListView, $iItem, $iSubitem), $iSubitem)      EndIf             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)     Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC $timer = TimerInit()     $tagDRAWITEMSTRUCT = DllStructCreate( _             "uint cType;" & _             "uint cID;" & _             "uint itmID;" & _             "uint itmAction;" & _             "uint itmState;" & _             "hwnd hItm;" & _             "hwnd hDC;" & _             "int itmRect[4];" & _             "dword itmData" _             , $lParam)     If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG     $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")     $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")     $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")     $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")     $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")     $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")     Local $aDefaultVariables[9] = [$tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC]     Switch $cID ; will look for ControlID, not window handle.         Case $cListView             Switch $itmAction                 Case $ODA_DRAWENTIRE                     Local $aRowColors[2] = [0xFDFDFD, 0xEEDDBB]                     Local $aRectMargins[4] = [6, -1, -4, 0]                     Local $aTextFormatting[5] = [-1, _        BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_CENTER, $DT_END_ELLIPSIS), _                             BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_CENTER, $DT_END_ELLIPSIS), _                             BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_RIGHT, $DT_END_ELLIPSIS), _        BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_END_ELLIPSIS)]                     __WM_DRAWITEM_ListView($hListView, $aDefaultVariables, $aRowColors, $aRectMargins, $aTextFormatting)     ; end case    EndSwitch   ; end case   Case $cListView_2    Switch $itmAction                 Case $ODA_DRAWENTIRE                     Local $aRowColors[2] = [0xFDFDFD, 0x00FFFF]                     Local $aRectMargins[4] = [6, -1, 0, 0]                     Local $aTextFormatting[3] = [BitOR($DT_VCENTER, $DT_SINGLELINE), _                             BitOR($DT_VCENTER, $DT_SINGLELINE), _                             BitOR($DT_VCENTER, $DT_SINGLELINE)]                     __WM_DRAWITEM_ListView($hListView_2, $aDefaultVariables, $aRowColors, $aRectMargins, $aTextFormatting)     ; end case    EndSwitch   ; end case     EndSwitch ConsoleWrite(Round(TimerDiff($timer),2) & @TAB & "WM_DRAWITEM" & @CRLF)     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_DRAWITEM Func __WM_DRAWITEM_ListView($hListView, ByRef $aDefaultVariables, ByRef $aRowColors, ByRef $aRectMargins, ByRef $aTextFormatting)     Local $iSubItemCount = _GUICtrlListView_GetColumnCount($hListView)     If UBound($aTextFormatting) < $iSubItemCount Then         ConsoleWrite("!> Error: invalid parameters in __WM_DRAWITEM_ListView()" & @CRLF)         Return     EndIf     Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC     $tagDRAWITEMSTRUCT = $aDefaultVariables[0]     $iBrushColor = $aDefaultVariables[1]     $cID = $aDefaultVariables[2]     $itmID = $aDefaultVariables[3]     $itmAction = $aDefaultVariables[4]     $itmState = $aDefaultVariables[5]     $hItm = $aDefaultVariables[6]     $hDC = $aDefaultVariables[7]     If _GUICtrlListView_GetItemSelected($hListView, $itmID) Then         $iBrushColor = $aRowColors[1]     Else         $iBrushColor = $aRowColors[0]     EndIf     ; create a brush with the desired color:     Local $aBrush = DllCall("gdi32.dll", "hwnd", "CreateSolidBrush", "int", $iBrushColor)     ; get the rectangle for the whole row and fill it:     Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)     DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 0, 1) ; +0 is the left margin     _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])     ; draw the text in each subitem     For $i = 0 To $iSubItemCount - 1         ; get subitem text:         Local $iSubItmText = _GUICtrlListView_GetItemText($hListView, $itmID, $i)         ; get subitem coordinates for drawing its respective text:         Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hListView, $itmID, $i)         ; the function above accepts not only subitems (one-based index), but also main item (index=0)   ; pass the coordinates to a DLL struct:         Local $iSubItmRect = DllStructCreate("int Left;int Top;int Right;int Bottom")         DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + $aRectMargins[0]) ; left margin         DllStructSetData($iSubItmRect, 2, $aSubItmRect[1] + $aRectMargins[1]) ; upper margin         DllStructSetData($iSubItmRect, 3, $aSubItmRect[2] + $aRectMargins[2]) ; right margin         DllStructSetData($iSubItmRect, 4, $aSubItmRect[3] + $aRectMargins[3]) ; bottom margin         Local $tRect = DllStructGetPtr($iSubItmRect)   If $cID == $cListView And StringLen($iSubItmText) > 0 And $aTextFormatting[$i] <> -1 Then    Local $hIcon = _GUIImageList_GetIcon($hIml_Listview, _GUICtrlListView_GetItemImage($hListView, $itmID, $i))    If @error Then ConsoleWrite("error 1" & @CRLF)    If $i = 0 Then ; the first column of a listview needs more handling than the other columns (sub-items)     #cs     ; positioning for the icon:     DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 12)     _WinAPI_DrawIconEx($hDC, DllStructGetData($iSubItmRect, "Left") - 16, Int((DllStructGetData($iSubItmRect, "Bottom") + DllStructGetData($iSubItmRect, "Top") - 16)/2) + $iAdjustV, $hIcon, 16, 16)     ; positioning for the text:     DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 4)     #ce    Else     If $i == 2 Then      _WinAPI_DrawIconEx($hDC, DllStructGetData($iSubItmRect, "Left"), Int((DllStructGetData($iSubItmRect, "Bottom") + DllStructGetData($iSubItmRect, "Top") - 16)/2) + $iAdjustV, $hIcon, 16, 16)      ; positioning for the text:      DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 20)     EndIf    EndIf    _GUIImageList_DestroyIcon($hIcon)   EndIf         If $aTextFormatting[$i] = -1 Then    ; do nothing (don't draw any text)         Else             _WinAPI_DrawText($hDC, $iSubItmText, $tRect, $aTextFormatting[$i])         EndIf     Next EndFunc   ;==>__WM_DRAWITEM_ListView Func WM_MEASUREITEM($hWnd, $Msg, $wParam, $lParam) Local $tMEASUREITEMS = DllStructCreate("uint cType;uint cID;uint itmID;uint itmW;uint itmH;ulong_ptr itmData", $lParam) If DllStructGetData($tMEASUREITEMS, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG DllStructSetData($tMEASUREITEMS, "itmH", $iListView_row_height) ; row height Return 1 EndFunc   ;==>WM_MEASUREITEM ; Based on File to Base64 String Code Generator ; by UEZ ; http://www.autoitscript.com/forum/topic/...ng-code-generator-v103-build-2 ;====================================================================================== ; Function Name:        Load_BMP_From_Mem ; Description:    Loads an image which is saved as a binary string and converts it to a bitmap or hbitmap ; ; Parameters:        $bImage:    the binary string which contains any valid image which is supported by GDI+ ; Optional:    $hHBITMAP:  if false a bitmap will be created, if true a hbitmap will be created ; ; Remark:            hbitmap format is used generally for GUI internal images, $bitmap is more a GDI+ image format ;                    Don't forget _GDIPlus_Startup() and _GDIPlus_Shutdown() ; ; Requirement(s):    GDIPlus.au3, Memory.au3 and _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Return Value(s):    Success: handle to bitmap (GDI+ bitmap format) or hbitmap (WinAPI bitmap format), ;                    Error: 0 ; Error codes:    1: $bImage is not a binary string ;                    2: unable to create stream on HGlobal ;                    3: unable to create bitmap from stream ; ; Author(s):            UEZ ; Additional Code:    thanks to progandy for the MemGlobalAlloc and tVARIANT lines and ;                    Yashied for _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Version:        v0.97 Build 2012-01-04 Beta ;======================================================================================= Func _Load_BMP_From_Mem($bImage, $hHBITMAP = False)     If Not IsBinary($bImage) Then Return SetError(1, 0, 0)     Local $aResult     Local Const $memBitmap = Binary($bImage) ;load image  saved in variable (memory) and convert it to binary     Local Const $len = BinaryLen($memBitmap) ;get length of image     Local Const $hData = _MemGlobalAlloc($len, $GMEM_MOVEABLE) ;allocates movable memory  ($GMEM_MOVEABLE = 0x0002)     Local Const $pData = _MemGlobalLock($hData) ;translate the handle into a pointer     Local $tMem = DllStructCreate("byte[" & $len & "]", $pData) ;create struct     DllStructSetData($tMem, 1, $memBitmap) ;fill struct with image data     _MemGlobalUnlock($hData) ;decrements the lock count  associated with a memory object that was allocated with GMEM_MOVEABLE     $aResult = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "handle", $pData, "int", True, "ptr*", 0) ;Creates a stream object that uses an HGLOBAL memory handle to store the stream contents     If @error Then SetError(2, 0, 0)     Local Const $hStream = $aResult[3]     $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromStream", "ptr", $hStream, "int*", 0) ;Creates a Bitmap object based on an IStream COM interface     If @error Then SetError(3, 0, 0)     Local Const $hBitmap = $aResult[2]     Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr")     DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, _             "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;release memory from $hStream to avoid memory leak     $tMem = 0     $tVARIANT = 0     If $hHBITMAP Then         Local Const $hHBmp = _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)         _GDIPlus_BitmapDispose($hBitmap)         Return $hHBmp     EndIf     Return $hBitmap EndFunc   ;==>_Load_BMP_From_Mem Func _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)     Local $tBIHDR, $Ret, $tData, $pBits, $hResult = 0     $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)     If (@error) Or ($Ret[0]) Then Return 0     $tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Ret[2], $Ret[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)     $pBits = DllStructGetData($tData, 'Scan0')     If Not $pBits Then Return 0     $tBIHDR = DllStructCreate('dword;long;long;ushort;ushort;dword;dword;long;long;dword;dword')     DllStructSetData($tBIHDR, 1, DllStructGetSize($tBIHDR))     DllStructSetData($tBIHDR, 2, $Ret[2])     DllStructSetData($tBIHDR, 3, $Ret[3])     DllStructSetData($tBIHDR, 4, 1)     DllStructSetData($tBIHDR, 5, 32)     DllStructSetData($tBIHDR, 6, 0)     $hResult = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBIHDR), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'dword', 0)     If (Not @error) And ($hResult[0]) Then         DllCall('gdi32.dll', 'dword', 'SetBitmapBits', 'ptr', $hResult[0], 'dword', $Ret[2] * $Ret[3] * 4, 'ptr', DllStructGetData($tData, 'Scan0'))         $hResult = $hResult[0]     Else         $hResult = 0     EndIf     _GDIPlus_BitmapUnlockBits($hBitmap, $tData)     Return $hResult EndFunc   ;==>_GDIPlus_BitmapCreateDIBFromBitmap Func _Decompress_Binary_String_to_Bitmap($Base64String)     $Base64String = Binary($Base64String)     Local $iSize_Source = BinaryLen($Base64String)     Local $pBuffer_Source = _WinAPI_CreateBuffer($iSize_Source)     DllStructSetData(DllStructCreate('byte[' & $iSize_Source & ']', $pBuffer_Source), 1, $Base64String)     Local $pBuffer_Decompress = _WinAPI_CreateBuffer(8388608)     Local $Size_Decompressed = _WinAPI_DecompressBuffer($pBuffer_Decompress, 8388608, $pBuffer_Source, $iSize_Source)     Local $b_Result = Binary(DllStructGetData(DllStructCreate('byte[' & $Size_Decompressed & ']', $pBuffer_Decompress), 1))     _WinAPI_FreeMemory($pBuffer_Source)     _WinAPI_FreeMemory($pBuffer_Decompress)     Return $b_Result EndFunc   ;==>_Decompress_Binary_String_to_Bitmap Func _Icon_Image_Checkbox_Unchecked()     Local $Base64String     $Base64String &= '7rBIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAANfc3ADZ3t4AANvg4ADe4uIAAOLl5QDl6OgAAOns7ADs7+8AAO/x8QDx8/MAAPT19QD29/cAAPj5+QD6+/sAAPz9/QD+/v7wAP///xNc/wB/AD8A/z8APwA/AD8APwA/AD8ACAAb4HYLAAEJAOEBCgsMAA0ODxAREhISbeIBCQcC4gEIBwLiAQfbBwLiAQYHAuIBBQcC4gG2BAcC4gEDBwLiAQIHAv/jAQcC5AEGAuIB7BceAOCfHgN/AG0A4QZhAA=='     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Unchecked Func _Icon_Image_Checkbox_Checked()     Local $Base64String     $Base64String &= 'z7BIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAAISEhADe3t5AAN7n5wDnAQbvCO8A7wEG9/cA9/EABv///xN4/wE/AD8A/z8APwA/AD8AHwAMAOB6CwAGAQkA4QEHCAkJCR4KAgDjAQcC5AEHCAKDAwLiAQYHBwICAwI54gEFBsABAwLjAQUCxgIkBOIBBAUCRQbjAVgEBQUCAuQBAwUCCPPkAQUCBwjkAQYC4gHsF3seAOCfA38AbQDhBmEA'     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Checked Func _Base64Decode($input_string)     Local $struct = DllStructCreate("int")     Local $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", 0, "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(1, 0, "")     Local $a = DllStructCreate("byte[" & DllStructGetData($struct, 1) & "]")     $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", DllStructGetPtr($a), "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(2, 0, "")     Return DllStructGetData($a, 1) EndFunc   ;==>_Base64Decode

Any thoughts?
Once again, thanks.

#13 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 14 April 2012 - 12:51 AM

Okay so here is my alternative for _GUI_ListView_AddArray().
It is of course slower but it's working flawlessly for me ;)

AutoIt         
Func __GUI_ListView_Add_Array($hListView, ByRef $array) If Not IsArray($array) Then Return SetError(1, 0, 0) ; not an array Local $iColumnCount = _GUICtrlListView_GetColumnCount($hListView) ; if the number of columns between the array and the listview doesn't match: If UBound($array,2) <> $iColumnCount Then Return SetError(3, 1, 0) Switch UBound($array, 0)   Case 1 ; 1-dimensioned array    _GUICtrlListView_BeginUpdate($hListView)    For $r = 0 To UBound($array, 1) - 1     _GUICtrlListView_AddItem($hListView, $array[$r], 0)    Next    _GUICtrlListView_EndUpdate($hListView)   Case 2 ; 2-dimensioned array    _GUICtrlListView_BeginUpdate($hListView)    Local $first_row    For $r = 0 To UBound($array, 1) - 1     If $r = 0 Then      $first_row = _GUICtrlListView_AddItem($hListView, $array[$r][0], 0)     Else      _GUICtrlListView_AddItem($hListView, $array[$r][0], 0)     EndIf    Next    For $r = 0 To UBound($array, 1) - 1     For $c = 1 To UBound($array, 2) - 1      _GUICtrlListView_AddSubItem($hListView, $first_row + $r, $array[$r][$c], $c, 0)     Next    Next    _GUICtrlListView_EndUpdate($hListView)   Case Else    Return SetError(2, 0, 0) ; invalid array (over 2 dimensions) EndSwitch Return EndFunc


#14 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 18 April 2012 - 05:32 PM

Instead of creating a new topic I chose to post here. This way we may be able to gather the necessary code to demonstrate all the personalizations in a single ListView.

Edit in Place isn't for now one of the things I need or have in mind for my current project.
One awesome example:
http://www.autoitscript.com/forum/topic/95854-grid-input/page__p__689068#entry689068

And this example that I remember seeing working in the past, but now the code is outdated; haven't looked at it in a while:
http://www.autoitscript.com/forum/topic/44132-edit-in-place-listview-multi-column/


As for the multiline, I found a trick:
Display multiline content with fly-over tooltips:
http://www.autoitscript.com/forum/topic/96826-listview-displaying-multiline-text-cells/page__view__findpost__p__697854

It does what it says, but it's not very helpful (visually) and it's a bit annoying.
I have an idea, though. I just need a little help: ;)

AutoIt         
#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Array.au3> #include <GDIPlus.au3> #include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> ;#include <APIConstants.au3> #include <WinAPIEx.au3> ; from <a href='http://www.autoitscript.com/forum/topic/98712-winapiex-udf/' class='bbc_url' title=''>http://www.autoitscript.com/forum/topic/98712-winapiex-udf/</a> Global Const $ODT_LISTVIEW = 102 Global Const $ODA_DRAWENTIRE = 0x1 ; #################################### ; adjustment of the icon positioning, according to windows version Global $iAdjustV = 0 If $__WINVER > 0x0600 Then $iAdjustV = 1 ; $__WINVER defined in WinAPIEx, $__WINVER > 0x0600 means Vista+ ; #################################### ; WM_MEASUREITEM allows setting the row height Global $iListView_row_height = 50 GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM") ; place before listview creation - message sent once for each ownerdrawn control created ;GUIRegisterMsg($WM_MEASUREITEM, "") ; call this after last ownerdrawn listview created ; --------------------------------------------------- _GDIPlus_Startup() $hGUI = GUICreate("ListView Set Item State", 700, 300) $cButton_CheckAll = GUICtrlCreateButton("Check All", 10, 275, 100, 20) $cButton_UncheckAll = GUICtrlCreateButton("UnCheck All", 120, 275, 100, 20) $cButton_StatesToArray = GUICtrlCreateButton("States to Array", 230, 275, 100, 20) ; listview 1 ----------------------------------------------- $iListView_row_height = 25 $cListView = GUICtrlCreateListView("", 2, 2, 394, 268, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED, $LVS_SHOWSELALWAYS, $LVS_SINGLESEL)) GUICtrlSetFont(-1, 11, 400, 0, "Calibri", 5) $hListView = GUICtrlGetHandle($cListView) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $LVS_EX_SUBITEMIMAGES)) $hIml_Listview = _GUIImageList_Create(16, 16, 5, 3) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Unchecked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Checked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) ; ########################################################## ; this "breaks" WM_MEASUREITEM ;_GUICtrlListView_SetImageList($hListView, $hIml_Listview, 1) ; why do we need this anyway? ; ########################################################## ; Add columns _GUICtrlListView_AddColumn($hListView, " ", 0) For $i = 1 To 3     _GUICtrlListView_AddColumn($hListView, "Column " & $i, 100) Next Local $aItems[30][4] For $row = 1 To 30 $aItems[$row-1][0] = "this won't show up" $aItems[$row-1][1] = "Row " & $row & ": Col 1" $aItems[$row-1][2] = "Row " & $row & ": Col 2" $aItems[$row-1][3] = "Row " & $row & ": Col 3" Next ; if you add items via _GUICtrlListView_AddArray(), the drawing will become unstable. ; also, the checkboxes don't appear unless you click their respective subitem. _GUICtrlListView_DeleteAllItems($hListView) ;_GUICtrlListView_AddArray($hListView, $aItems) __GUI_ListView_Add_Array($hListView, $aItems) ; workaround ; ----------------------------------------------------------- ; listview 2 ----------------------------------------------- $iListView_row_height = 40 $cListView_2 = GUICtrlCreateListView("", 400, 2, 298, 268, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED, $LVS_SHOWSELALWAYS)) GUICtrlSetFont(-1, 11, 400, 0, "Calibri", 5) $hListView_2 = GUICtrlGetHandle($cListView_2) _GUICtrlListView_SetExtendedListViewStyle($hListView_2, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES)) ; Add columns For $i = 1 To 3     _GUICtrlListView_AddColumn($hListView_2, "2 - Column " & $i, 90) Next ; Add items For $row = 1 To 20     _GUICtrlListView_AddItem($hListView_2, "Row " & $row & ": Col 0", 0)     _GUICtrlListView_AddSubItem($hListView_2, $row - 1, "Row " & $row & ", resize me!" & @CRLF & "-----------Col 1", 1, 0)     If $row <> 3 Then   _GUICtrlListView_AddSubItem($hListView_2, $row - 1, "Row " & $row & ": Col 2", 2, 0) Else   ; if you comment the line below and click+drag to resize this ListView's columns, the drawing will become unstable   _GUICtrlListView_AddSubItem($hListView_2, $row - 1, "", 2, 0) EndIf Next ; ----------------------------------------------------------- GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") GUISetState() ; Loop until user exits While 1     Switch GUIGetMsg()         Case $GUI_EVENT_CLOSE             ExitLoop         Case $cButton_CheckAll             _LV_ImgCheckboxes_CheckAll($hListView)         Case $cButton_UncheckAll             _LV_ImgCheckboxes_UncheckAll($hListView)         Case $cButton_StatesToArray             $aLVStates = _LV_ImgCheckboxes_StatesToArray($hListView)             _ArrayDisplay($aLVStates)     EndSwitch WEnd GUIDelete() _GUIImageList_Destroy($hIml_Listview) _GDIPlus_Shutdown() Exit Func _LV_ImgCheckboxes_CheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 1, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_CheckAll Func _LV_ImgCheckboxes_UncheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 0, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_UncheckAll Func _LV_ImgCheckboxes_StatesToArray($hWnd)     Local $iColumns = _GUICtrlListView_GetColumnCount($hWnd)     If $iColumns = 0 Then Return SetError(1)     Local $iItems = _GUICtrlListView_GetItemCount($hWnd)     If $iItems = 0 Then Return SetError(2)     Local $aStates[$iItems][$iColumns]     For $i = 0 To $iItems - 1         For $y = 0 To $iColumns - 1             $aStates[$i][$y] = _GUICtrlListView_GetItemImage($hWnd, $i, $y)         Next     Next     Return $aStates EndFunc   ;==>_LV_ImgCheckboxes_StatesToArray Func __GUI_ListView_Add_Array($hListView, ByRef $array) If Not IsArray($array) Then Return SetError(1, 0, 0) ; not an array Local $iColumnCount = _GUICtrlListView_GetColumnCount($hListView) ; if the number of columns between the array and the listview doesn't match: If UBound($array,2) <> $iColumnCount Then Return SetError(3, 1, 0) Switch UBound($array, 0)   Case 1 ; 1-dimensioned array    _GUICtrlListView_BeginUpdate($hListView)    For $r = 0 To UBound($array, 1) - 1     _GUICtrlListView_AddItem($hListView, $array[$r], 0)    Next    _GUICtrlListView_EndUpdate($hListView)   Case 2 ; 2-dimensioned array    _GUICtrlListView_BeginUpdate($hListView)    Local $first_row    For $r = 0 To UBound($array, 1) - 1     If $r = 0 Then      $first_row = _GUICtrlListView_AddItem($hListView, $array[$r][0], 0)     Else      _GUICtrlListView_AddItem($hListView, $array[$r][0], 0)     EndIf    Next    For $r = 0 To UBound($array, 1) - 1     For $c = 1 To UBound($array, 2) - 1      _GUICtrlListView_AddSubItem($hListView, $first_row + $r, $array[$r][$c], $c, 0)     Next    Next    _GUICtrlListView_EndUpdate($hListView)   Case Else    Return SetError(2, 0, 0) ; invalid array (over 2 dimensions) EndSwitch Return EndFunc Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)     Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)     Local $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")     Local $nNotifyCode = DllStructGetData($tNMHDR, "Code")     Switch $hWndFrom         Case $hListView             Switch $nNotifyCode                 Case $NM_CLICK                     Local $tINFO = DllStructCreate($tagNMITEMACTIVATE, $lParam)                     Local $iItem = DllStructGetData($tINFO, "Index")                     Local $iSubitem = DllStructGetData($tINFO, "SubItem")                     If $iSubitem == 2 And StringLen(_GUICtrlListView_GetItemText($hListView, $iItem, $iSubitem)) > 0 Then       ;ConsoleWrite("painting row "&$iItem+1&"   col "&$iSubitem+1&@CRLF)       _GUICtrlListView_SetItemImage($hListView, $iItem, Not _GUICtrlListView_GetItemImage($hListView, $iItem, $iSubitem), $iSubitem)      EndIf             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)     Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC $timer = TimerInit()     $tagDRAWITEMSTRUCT = DllStructCreate( _             "uint cType;" & _             "uint cID;" & _             "uint itmID;" & _             "uint itmAction;" & _             "uint itmState;" & _             "hwnd hItm;" & _             "hwnd hDC;" & _             "int itmRect[4];" & _             "dword itmData" _             , $lParam)     If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG     $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")     $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")     $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")     $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")     $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")     $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")     Local $aDefaultVariables[9] = [$tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC]     Switch $cID ; will look for ControlID, not window handle.         Case $cListView             Switch $itmAction                 Case $ODA_DRAWENTIRE                     Local $aRowColors[2] = [0xFDFDFD, 0xEEDDBB]                     Local $aRectMargins[4] = [6, -1, -4, 0]                     Local $aTextFormatting[5] = [-1, _        BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_CENTER, $DT_END_ELLIPSIS), _                             BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_CENTER, $DT_END_ELLIPSIS), _                             BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_RIGHT, $DT_END_ELLIPSIS), _        BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_END_ELLIPSIS)]                     __WM_DRAWITEM_ListView($hListView, $aDefaultVariables, $aRowColors, $aRectMargins, $aTextFormatting)     ; end case    EndSwitch   ; end case   Case $cListView_2    Switch $itmAction                 Case $ODA_DRAWENTIRE                     Local $aRowColors[2] = [0xFDFDFD, 0x00FFFF]                     Local $aRectMargins[4] = [6, -1, 0, 0]                     Local $aTextFormatting[3] = [BitOR($DT_VCENTER, $DT_SINGLELINE), _                             BitOR($DT_EDITCONTROL, $DT_WORDBREAK), _                             BitOR($DT_VCENTER, $DT_SINGLELINE)]                     __WM_DRAWITEM_ListView($hListView_2, $aDefaultVariables, $aRowColors, $aRectMargins, $aTextFormatting)     ; end case    EndSwitch   ; end case     EndSwitch ConsoleWrite(Round(TimerDiff($timer),2) & @TAB & "WM_DRAWITEM" & @CRLF)     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_DRAWITEM Func __WM_DRAWITEM_ListView($hListView, ByRef $aDefaultVariables, ByRef $aRowColors, ByRef $aRectMargins, ByRef $aTextFormatting) Local $iSubItemCount = _GUICtrlListView_GetColumnCount($hListView) If UBound($aTextFormatting) < $iSubItemCount Then   ConsoleWrite("!> Error: invalid parameters in __WM_DRAWITEM_ListView()" & @CRLF)   Return EndIf Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC $tagDRAWITEMSTRUCT = $aDefaultVariables[0] $iBrushColor = $aDefaultVariables[1] $cID = $aDefaultVariables[2] $itmID = $aDefaultVariables[3] $itmAction = $aDefaultVariables[4] $itmState = $aDefaultVariables[5] $hItm = $aDefaultVariables[6] $hDC = $aDefaultVariables[7] If _GUICtrlListView_GetItemSelected($hListView, $itmID) Then   $iBrushColor = $aRowColors[1] Else   $iBrushColor = $aRowColors[0] EndIf ; create a brush with the desired color: Local $aBrush = DllCall("gdi32.dll", "hwnd", "CreateSolidBrush", "int", $iBrushColor) ; get the rectangle for the whole row and fill it: Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1) DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 0, 1) ; +0 is the left margin _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0]) ; draw the text in each subitem For $i = 0 To $iSubItemCount - 1   ; get subitem text:   Local $iSubItmText = _GUICtrlListView_GetItemText($hListView, $itmID, $i)   ; get subitem coordinates for drawing its respective text:   Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hListView, $itmID, $i)   ; the function above accepts not only subitems (one-based index), but also main item (index=0)   ; pass the coordinates to a DLL struct:   Local $iSubItmRect = DllStructCreate("int Left;int Top;int Right;int Bottom")   DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + $aRectMargins[0]) ; left margin   DllStructSetData($iSubItmRect, 2, $aSubItmRect[1] + $aRectMargins[1]) ; upper margin   DllStructSetData($iSubItmRect, 3, $aSubItmRect[2] + $aRectMargins[2]) ; right margin   DllStructSetData($iSubItmRect, 4, $aSubItmRect[3] + $aRectMargins[3]) ; bottom margin   Local $tRect = DllStructGetPtr($iSubItmRect)   ;#cs   If $cID == $cListView And StringLen($iSubItmText) > 0 And $aTextFormatting[$i] <> - 1 Then    Local $hIcon = _GUIImageList_GetIcon($hIml_Listview, _GUICtrlListView_GetItemImage($hListView, $itmID, $i))    If $i = 0 Then ; the first column of a listview needs more handling than the other columns (sub-items)     #cs      ; positioning for the icon:      DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 12)      _WinAPI_DrawIconEx($hDC, DllStructGetData($iSubItmRect, "Left") - 16, Int((DllStructGetData($iSubItmRect, "Bottom") + DllStructGetData($iSubItmRect, "Top") - 16)/2) + $iAdjustV, $hIcon, 16, 16)      ; positioning for the text:      DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 4)     #ce    ElseIf $i == 2 Then     _WinAPI_DrawIconEx($hDC, DllStructGetData($iSubItmRect, "Left"), Int((DllStructGetData($iSubItmRect, "Bottom") + DllStructGetData($iSubItmRect, "Top") - 16) / 2) - 1 + $iAdjustV, $hIcon, 16, 16)     ; positioning for the text:     DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 20)    EndIf    _GUIImageList_DestroyIcon($hIcon)   EndIf   ;#ce   If $aTextFormatting[$i] = -1 Then    ; do nothing (don't draw any text)   Else    _WinAPI_DrawText($hDC, $iSubItmText, $tRect, $aTextFormatting[$i])   EndIf Next EndFunc   ;==>__WM_DRAWITEM_ListView Func WM_MEASUREITEM($hWnd, $Msg, $wParam, $lParam) Local $tMEASUREITEMS = DllStructCreate("uint cType;uint cID;uint itmID;uint itmW;uint itmH;ulong_ptr itmData", $lParam) If DllStructGetData($tMEASUREITEMS, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG DllStructSetData($tMEASUREITEMS, "itmH", $iListView_row_height) ; row height Return 1 EndFunc   ;==>WM_MEASUREITEM ; Based on File to Base64 String Code Generator ; by UEZ ; <a href='http://www.autoitscript.com/forum/topic/...ng-code-generator-v103-build-2' class='bbc_url' title=''>http://www.autoitscript.com/forum/topic/...ng-code-generator-v103-build-2</a> ;====================================================================================== ; Function Name:        Load_BMP_From_Mem ; Description:    Loads an image which is saved as a binary string and converts it to a bitmap or hbitmap ; ; Parameters:        $bImage:    the binary string which contains any valid image which is supported by GDI+ ; Optional:    $hHBITMAP:  if false a bitmap will be created, if true a hbitmap will be created ; ; Remark:            hbitmap format is used generally for GUI internal images, $bitmap is more a GDI+ image format ;                    Don't forget _GDIPlus_Startup() and _GDIPlus_Shutdown() ; ; Requirement(s):    GDIPlus.au3, Memory.au3 and _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Return Value(s):    Success: handle to bitmap (GDI+ bitmap format) or hbitmap (WinAPI bitmap format), ;                    Error: 0 ; Error codes:    1: $bImage is not a binary string ;                    2: unable to create stream on HGlobal ;                    3: unable to create bitmap from stream ; ; Author(s):            UEZ ; Additional Code:    thanks to progandy for the MemGlobalAlloc and tVARIANT lines and ;                    Yashied for _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Version:        v0.97 Build 2012-01-04 Beta ;======================================================================================= Func _Load_BMP_From_Mem($bImage, $hHBITMAP = False)     If Not IsBinary($bImage) Then Return SetError(1, 0, 0)     Local $aResult     Local Const $memBitmap = Binary($bImage) ;load image  saved in variable (memory) and convert it to binary     Local Const $len = BinaryLen($memBitmap) ;get length of image     Local Const $hData = _MemGlobalAlloc($len, $GMEM_MOVEABLE) ;allocates movable memory  ($GMEM_MOVEABLE = 0x0002)     Local Const $pData = _MemGlobalLock($hData) ;translate the handle into a pointer     Local $tMem = DllStructCreate("byte[" & $len & "]", $pData) ;create struct     DllStructSetData($tMem, 1, $memBitmap) ;fill struct with image data     _MemGlobalUnlock($hData) ;decrements the lock count  associated with a memory object that was allocated with GMEM_MOVEABLE     $aResult = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "handle", $pData, "int", True, "ptr*", 0) ;Creates a stream object that uses an HGLOBAL memory handle to store the stream contents     If @error Then SetError(2, 0, 0)     Local Const $hStream = $aResult[3]     $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromStream", "ptr", $hStream, "int*", 0) ;Creates a Bitmap object based on an IStream COM interface     If @error Then SetError(3, 0, 0)     Local Const $hBitmap = $aResult[2]     Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr")     DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, _             "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;release memory from $hStream to avoid memory leak     $tMem = 0     $tVARIANT = 0     If $hHBITMAP Then         Local Const $hHBmp = _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)         _GDIPlus_BitmapDispose($hBitmap)         Return $hHBmp     EndIf     Return $hBitmap EndFunc   ;==>_Load_BMP_From_Mem Func _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)     Local $tBIHDR, $Ret, $tData, $pBits, $hResult = 0     $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)     If (@error) Or ($Ret[0]) Then Return 0     $tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Ret[2], $Ret[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)     $pBits = DllStructGetData($tData, 'Scan0')     If Not $pBits Then Return 0     $tBIHDR = DllStructCreate('dword;long;long;ushort;ushort;dword;dword;long;long;dword;dword')     DllStructSetData($tBIHDR, 1, DllStructGetSize($tBIHDR))     DllStructSetData($tBIHDR, 2, $Ret[2])     DllStructSetData($tBIHDR, 3, $Ret[3])     DllStructSetData($tBIHDR, 4, 1)     DllStructSetData($tBIHDR, 5, 32)     DllStructSetData($tBIHDR, 6, 0)     $hResult = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBIHDR), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'dword', 0)     If (Not @error) And ($hResult[0]) Then         DllCall('gdi32.dll', 'dword', 'SetBitmapBits', 'ptr', $hResult[0], 'dword', $Ret[2] * $Ret[3] * 4, 'ptr', DllStructGetData($tData, 'Scan0'))         $hResult = $hResult[0]     Else         $hResult = 0     EndIf     _GDIPlus_BitmapUnlockBits($hBitmap, $tData)     Return $hResult EndFunc   ;==>_GDIPlus_BitmapCreateDIBFromBitmap Func _Decompress_Binary_String_to_Bitmap($Base64String)     $Base64String = Binary($Base64String)     Local $iSize_Source = BinaryLen($Base64String)     Local $pBuffer_Source = _WinAPI_CreateBuffer($iSize_Source)     DllStructSetData(DllStructCreate('byte[' & $iSize_Source & ']', $pBuffer_Source), 1, $Base64String)     Local $pBuffer_Decompress = _WinAPI_CreateBuffer(8388608)     Local $Size_Decompressed = _WinAPI_DecompressBuffer($pBuffer_Decompress, 8388608, $pBuffer_Source, $iSize_Source)     Local $b_Result = Binary(DllStructGetData(DllStructCreate('byte[' & $Size_Decompressed & ']', $pBuffer_Decompress), 1))     _WinAPI_FreeMemory($pBuffer_Source)     _WinAPI_FreeMemory($pBuffer_Decompress)     Return $b_Result EndFunc   ;==>_Decompress_Binary_String_to_Bitmap Func _Icon_Image_Checkbox_Unchecked()     Local $Base64String     $Base64String &= '7rBIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAANfc3ADZ3t4AANvg4ADe4uIAAOLl5QDl6OgAAOns7ADs7+8AAO/x8QDx8/MAAPT19QD29/cAAPj5+QD6+/sAAPz9/QD+/v7wAP///xNc/wB/AD8A/z8APwA/AD8APwA/AD8ACAAb4HYLAAEJAOEBCgsMAA0ODxAREhISbeIBCQcC4gEIBwLiAQfbBwLiAQYHAuIBBQcC4gG2BAcC4gEDBwLiAQIHAv/jAQcC5AEGAuIB7BceAOCfHgN/AG0A4QZhAA=='     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Unchecked Func _Icon_Image_Checkbox_Checked()     Local $Base64String     $Base64String &= 'z7BIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAAISEhADe3t5AAN7n5wDnAQbvCO8A7wEG9/cA9/EABv///xN4/wE/AD8A/z8APwA/AD8AHwAMAOB6CwAGAQkA4QEHCAkJCR4KAgDjAQcC5AEHCAKDAwLiAQYHBwICAwI54gEFBsABAwLjAQUCxgIkBOIBBAUCRQbjAVgEBQUCAuQBAwUCCPPkAQUCBwjkAQYC4gHsF3seAOCfA38AbQDhBmEA'     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Checked Func _Base64Decode($input_string)     Local $struct = DllStructCreate("int")     Local $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", 0, "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(1, 0, "")     Local $a = DllStructCreate("byte[" & DllStructGetData($struct, 1) & "]")     $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", DllStructGetPtr($a), "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(2, 0, "")     Return DllStructGetData($a, 1) EndFunc   ;==>_Base64Decode


For me this is awesome already.
But how would I draw different font sizes, or even different fonts, within the same subitem? In essential trying to resemble the Outlook lists (From, Subject, Body, all into one "cell").

And then there's the vertical alignment. $DT_VCENTER only seems to work with single line.

#15 rover

rover

    unmutual

  • Active Members
  • PipPipPipPipPipPip
  • 825 posts

Posted 18 April 2012 - 11:19 PM

It's ownerdrawing, and you have the items DC, so the world's your oyster.

A rough outline of how to set multiline text fonts/colour.

You could probably compose an items image in an off-screen DC, then bitblit to the item DC

Includes a gratuitous example of using a theme part for item selection.

Edit: corrected ODS_SELECTED multiple item selection


AutoIt         
#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Array.au3> #include <GDIPlus.au3> #include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> ;#include <APIConstants.au3> #include <WinAPIEx.au3> ; from <a href='http://www.autoitscript.com/forum/topic/98712-winapiex-udf/' class='bbc_url' title=''>http://www.autoitscript.com/forum/topic/98712-winapiex-udf/</a> #include <FontConstants.au3> Global $aFont[3] $aFont[0] = _WinAPI_CreateFont(20, 0, 0, 0, $FW_MEDIUM, False, False, False, _         $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, 'Times New Roman') $aFont[1] = _WinAPI_CreateFont(18, 0, 0, 0, $FW_MEDIUM, False, False, False, _         $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, 'Tahoma') $aFont[2] = _WinAPI_CreateFont(32, 6, 0, 0, $FW_BOLD, False, False, False, _         $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, 'Comic Sans MS') Global $hThemex = DllCall('uxtheme.dll', 'ptr', 'OpenThemeData', 'hwnd', 0, 'wstr', 'Button') $hThemex = $hThemex[0] Global Const $ODS_SELECTED = 0x0001 Global Const $ODT_LISTVIEW = 102 Global Const $ODA_DRAWENTIRE = 0x1 ; #################################### ; adjustment of the icon positioning, according to windows version Global $iAdjustV = 0 If $__WINVER > 0x0600 Then $iAdjustV = 1 ; $__WINVER defined in WinAPIEx, $__WINVER > 0x0600 means Vista+ ; #################################### ; WM_MEASUREITEM allows setting the row height Global $iListView_row_height = 50 GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM") ; place before listview creation - message sent once for each ownerdrawn control created ;GUIRegisterMsg($WM_MEASUREITEM, "") ; call this after last ownerdrawn listview created ; --------------------------------------------------- _GDIPlus_Startup() $hGUI = GUICreate("ListView Set Item State", 700, 300) $cButton_CheckAll = GUICtrlCreateButton("Check All", 10, 275, 100, 20) $cButton_UncheckAll = GUICtrlCreateButton("UnCheck All", 120, 275, 100, 20) $cButton_StatesToArray = GUICtrlCreateButton("States to Array", 230, 275, 100, 20) ; listview 1 ----------------------------------------------- $iListView_row_height = 25 $cListView = GUICtrlCreateListView("", 2, 2, 394, 268, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED, $LVS_SHOWSELALWAYS, $LVS_SINGLESEL)) GUICtrlSetFont(-1, 11, 400, 0, "Calibri", 5) $hListView = GUICtrlGetHandle($cListView) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $LVS_EX_SUBITEMIMAGES)) $hIml_Listview = _GUIImageList_Create(16, 16, 5, 3) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Unchecked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) $hBitmap_Icon = _Load_BMP_From_Mem(_Icon_Image_Checkbox_Checked(), True) _GUIImageList_Add($hIml_Listview, $hBitmap_Icon) _WinAPI_DeleteObject($hBitmap_Icon) ; ########################################################## ; this "breaks" WM_MEASUREITEM ;_GUICtrlListView_SetImageList($hListView, $hIml_Listview, 1) ; why do we need this anyway? ; ########################################################## ; Add columns _GUICtrlListView_AddColumn($hListView, " ", 0) For $i = 1 To 3     _GUICtrlListView_AddColumn($hListView, "Column " & $i, 100) Next Local $aItems[30][4] For $row = 1 To 30     $aItems[$row - 1][0] = "this won't show up"     $aItems[$row - 1][1] = "Row " & $row & ": Col 1"     $aItems[$row - 1][2] = "Row " & $row & ": Col 2"     $aItems[$row - 1][3] = "Row " & $row & ": Col 3" Next ; if you add items via _GUICtrlListView_AddArray(), the drawing will become unstable. ; also, the checkboxes don't appear unless you click their respective subitem. _GUICtrlListView_DeleteAllItems($hListView) ;_GUICtrlListView_AddArray($hListView, $aItems) __GUI_ListView_Add_Array($hListView, $aItems) ; workaround ; ----------------------------------------------------------- ; listview 2 ----------------------------------------------- $iListView_row_height = 80 $cListView_2 = GUICtrlCreateListView("", 400, 2, 298, 268, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED, $LVS_SHOWSELALWAYS)) GUICtrlSetFont(-1, 11, 400, 0, "Calibri", 5) $hListView_2 = GUICtrlGetHandle($cListView_2) _GUICtrlListView_SetExtendedListViewStyle($hListView_2, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES)) ; Add columns For $i = 1 To 3     _GUICtrlListView_AddColumn($hListView_2, "2 - Column " & $i, 90) Next ; Add items For $row = 1 To 20     _GUICtrlListView_AddItem($hListView_2, "Row " & $row & ": Col 0", 0)     _GUICtrlListView_AddSubItem($hListView_2, $row - 1, "Row " & $row & ", resize me!" & @CRLF & "-----------Col 1", 1, 0)     If $row <> 3 Then         _GUICtrlListView_AddSubItem($hListView_2, $row - 1, "Row " & $row & ": Col 2", 2, 0)     Else         ; if you comment the line below and click+drag to resize this ListView's columns, the drawing will become unstable         _GUICtrlListView_AddSubItem($hListView_2, $row - 1, "", 2, 0)     EndIf Next ; ----------------------------------------------------------- _GUICtrlListView_SetItemSelected($cListView_2, 0) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") GUISetState() ; Loop until user exits While 1     Switch GUIGetMsg()         Case $GUI_EVENT_CLOSE             ExitLoop         Case $cButton_CheckAll             _LV_ImgCheckboxes_CheckAll($hListView)         Case $cButton_UncheckAll             _LV_ImgCheckboxes_UncheckAll($hListView)         Case $cButton_StatesToArray             $aLVStates = _LV_ImgCheckboxes_StatesToArray($hListView)             _ArrayDisplay($aLVStates)     EndSwitch WEnd GUIDelete() DllCall('uxtheme.dll', 'uint', 'CloseThemeData', 'ptr', $hThemex) _GUIImageList_Destroy($hIml_Listview) _GDIPlus_Shutdown() For $i = 0 To UBound($aFont) - 1     If $aFont[$i] Then _WinAPI_DeleteObject($aFont[$i]) Next Exit Func _LV_ImgCheckboxes_CheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 1, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_CheckAll Func _LV_ImgCheckboxes_UncheckAll($hWnd)     _GUICtrlListView_BeginUpdate($hWnd)     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         For $y = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1             _GUICtrlListView_SetItemImage($hWnd, $i, 0, $y)         Next     Next     _GUICtrlListView_EndUpdate($hWnd) EndFunc   ;==>_LV_ImgCheckboxes_UncheckAll Func _LV_ImgCheckboxes_StatesToArray($hWnd)     Local $iColumns = _GUICtrlListView_GetColumnCount($hWnd)     If $iColumns = 0 Then Return SetError(1)     Local $iItems = _GUICtrlListView_GetItemCount($hWnd)     If $iItems = 0 Then Return SetError(2)     Local $aStates[$iItems][$iColumns]     For $i = 0 To $iItems - 1         For $y = 0 To $iColumns - 1             $aStates[$i][$y] = _GUICtrlListView_GetItemImage($hWnd, $i, $y)         Next     Next     Return $aStates EndFunc   ;==>_LV_ImgCheckboxes_StatesToArray Func __GUI_ListView_Add_Array($hListView, ByRef $array)     If Not IsArray($array) Then Return SetError(1, 0, 0) ; not an array     Local $iColumnCount = _GUICtrlListView_GetColumnCount($hListView)     ; if the number of columns between the array and the listview doesn't match:     If UBound($array, 2) <> $iColumnCount Then Return SetError(3, 1, 0)     Switch UBound($array, 0)         Case 1 ; 1-dimensioned array             _GUICtrlListView_BeginUpdate($hListView)             For $r = 0 To UBound($array, 1) - 1                 _GUICtrlListView_AddItem($hListView, $array[$r], 0)             Next             _GUICtrlListView_EndUpdate($hListView)         Case 2 ; 2-dimensioned array             _GUICtrlListView_BeginUpdate($hListView)             Local $first_row             For $r = 0 To UBound($array, 1) - 1                 If $r = 0 Then                     $first_row = _GUICtrlListView_AddItem($hListView, $array[$r][0], 0)                 Else                     _GUICtrlListView_AddItem($hListView, $array[$r][0], 0)                 EndIf             Next             For $r = 0 To UBound($array, 1) - 1                 For $c = 1 To UBound($array, 2) - 1                     _GUICtrlListView_AddSubItem($hListView, $first_row + $r, $array[$r][$c], $c, 0)                 Next             Next             _GUICtrlListView_EndUpdate($hListView)         Case Else             Return SetError(2, 0, 0) ; invalid array (over 2 dimensions)     EndSwitch     Return EndFunc   ;==>__GUI_ListView_Add_Array Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)     Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)     Local $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")     Local $nNotifyCode = DllStructGetData($tNMHDR, "Code")     Switch $hWndFrom         Case $hListView             Switch $nNotifyCode                 Case $NM_CLICK                     Local $tINFO = DllStructCreate($tagNMITEMACTIVATE, $lParam)                     Local $iItem = DllStructGetData($tINFO, "Index")                     Local $iSubitem = DllStructGetData($tINFO, "SubItem")                     If $iSubitem == 2 And StringLen(_GUICtrlListView_GetItemText($hListView, $iItem, $iSubitem)) > 0 Then                         ;ConsoleWrite("painting row "&$iItem+1&"   col "&$iSubitem+1&@CRLF)                         _GUICtrlListView_SetItemImage($hListView, $iItem, Not _GUICtrlListView_GetItemImage($hListView, $iItem, $iSubitem), $iSubitem)                     EndIf             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)     Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC     $timer = TimerInit()     $tagDRAWITEMSTRUCT = DllStructCreate( _             "uint cType;" & _             "uint cID;" & _             "uint itmID;" & _             "uint itmAction;" & _             "uint itmState;" & _             "hwnd hItm;" & _             "hwnd hDC;" & _             "int itmRect[4];" & _             "dword itmData" _             , $lParam)     If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG     $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")     $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")     $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")     $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")     $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")     $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")     Local $aDefaultVariables[9] = [$tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC]     Switch $cID ; will look for ControlID, not window handle.         Case $cListView             Switch $itmAction                 Case $ODA_DRAWENTIRE                     Local $aRowColors[2] = [0xFDFDFD, 0xEEDDBB]                     Local $aRectMargins[4] = [6, -1, -4, 0]                     Local $aTextFormatting[5] = [-1, _                             BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_CENTER, $DT_END_ELLIPSIS), _                             BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_CENTER, $DT_END_ELLIPSIS), _                             BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_RIGHT, $DT_END_ELLIPSIS), _                             BitOR($DT_VCENTER, $DT_SINGLELINE, $DT_END_ELLIPSIS)]                     __WM_DRAWITEM_ListView($hListView, $aDefaultVariables, $aRowColors, $aRectMargins, $aTextFormatting)                     ; end case             EndSwitch             ; end case         Case $cListView_2             Switch $itmAction                 Case $ODA_DRAWENTIRE                     Local $aRowColors[2] = [0xFDFDFD, 0x00FFFF]                     Local $aRectMargins[4] = [6, -1, 0, 0]                     Local $aTextFormatting[3] = [BitOR($DT_VCENTER, $DT_SINGLELINE), _                             BitOR($DT_EDITCONTROL, $DT_WORDBREAK), _                             BitOR($DT_VCENTER, $DT_SINGLELINE)]                     __WM_DRAWITEM_ListView($hListView_2, $aDefaultVariables, $aRowColors, $aRectMargins, $aTextFormatting)                     ; end case             EndSwitch             ; end case     EndSwitch     ConsoleWrite(Round(TimerDiff($timer), 2) & @TAB & "WM_DRAWITEM" & @CRLF)     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_DRAWITEM Func __WM_DRAWITEM_ListView($hLV, ByRef $aDefaultVariables, ByRef $aRowColors, ByRef $aRectMargins, ByRef $aTextFormatting)     Local $iSubItemCount = _GUICtrlListView_GetColumnCount($hLV)     If UBound($aTextFormatting) < $iSubItemCount Then         ConsoleWrite("!> Error: invalid parameters in __WM_DRAWITEM_ListView()" & @CRLF)         Return     EndIf     Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC     $tagDRAWITEMSTRUCT = $aDefaultVariables[0]     $iBrushColor = $aDefaultVariables[1]     $cID = $aDefaultVariables[2]     $itmID = $aDefaultVariables[3]     $itmAction = $aDefaultVariables[4]     $itmState = $aDefaultVariables[5]     $hItm = $aDefaultVariables[6]     $hDC = $aDefaultVariables[7]     If BitAND($itmState, $ODS_SELECTED) Then         $iBrushColor = $aRowColors[1]         DllCall('uxtheme.dll', 'uint', 'DrawThemeBackground', 'ptr', $hThemex, 'hwnd', $hDC, 'int', 1, 'int', 3, 'ptr', DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), 'ptr', 0)     Else         $iBrushColor = $aRowColors[0]         ; create a brush with the desired color:         Local $aBrush = DllCall("gdi32.dll", "hwnd", "CreateSolidBrush", "int", $iBrushColor)         ; get the rectangle for the whole row and fill it:         Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)         DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 0, 1) ; +0 is the left margin         _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])         _WinAPI_DeleteObject($aBrush[0])     EndIf     ; draw the text in each subitem     For $i = 0 To $iSubItemCount - 1         ; get subitem text:         Local $iSubItmText = _GUICtrlListView_GetItemText($hLV, $itmID, $i)         ; get subitem coordinates for drawing its respective text:         Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hLV, $itmID, $i)         ; the function above accepts not only subitems (one-based index), but also main item (index=0)         ; pass the coordinates to a DLL struct:         Local $iSubItmRect = DllStructCreate("int Left;int Top;int Right;int Bottom")         DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + $aRectMargins[0]) ; left margin         DllStructSetData($iSubItmRect, 2, $aSubItmRect[1] + $aRectMargins[1]) ; upper margin         DllStructSetData($iSubItmRect, 3, $aSubItmRect[2] + $aRectMargins[2]) ; right margin         DllStructSetData($iSubItmRect, 4, $aSubItmRect[3] + $aRectMargins[3]) ; bottom margin         Local $tRect = DllStructGetPtr($iSubItmRect)         ;#cs         If $cID == $cListView And StringLen($iSubItmText) > 0 And $aTextFormatting[$i] <> -1 Then             Local $hIcon = _GUIImageList_GetIcon($hIml_Listview, _GUICtrlListView_GetItemImage($hLV, $itmID, $i))             If $i = 0 Then ; the first column of a listview needs more handling than the other columns (sub-items)                 #cs                     ; positioning for the icon:                     DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 12)                     _WinAPI_DrawIconEx($hDC, DllStructGetData($iSubItmRect, "Left") - 16, Int((DllStructGetData($iSubItmRect, "Bottom") + DllStructGetData($iSubItmRect, "Top") - 16)/2) + $iAdjustV, $hIcon, 16, 16)                     ; positioning for the text:                     DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 4)                 #ce             ElseIf $i == 2 Then                 _WinAPI_DrawIconEx($hDC, DllStructGetData($iSubItmRect, "Left"), Int((DllStructGetData($iSubItmRect, "Bottom") + DllStructGetData($iSubItmRect, "Top") - 16) / 2) - 1 + $iAdjustV, $hIcon, 16, 16)                 ; positioning for the text:                 DllStructSetData($iSubItmRect, "Left", DllStructGetData($iSubItmRect, "Left") + 20)             EndIf             _GUIImageList_DestroyIcon($hIcon)         EndIf         ;#ce         If $aTextFormatting[$i] = -1 Then             ; do nothing (don't draw any text)         Else             Switch $hLV                 Case $hListView                     _WinAPI_DrawText($hDC, $iSubItmText, $tRect, $aTextFormatting[$i])                 Case $hListView_2                     If $i = 0 Then                         Local $iColPrev = _WinAPI_SetTextColor($hDC, 0x0000FF)                         Local $hFontOld = _WinAPI_SelectObject($hDC, $aFont[0])                         DllStructSetData($iSubItmRect, 2, $aSubItmRect[1] + $aRectMargins[1] + 2)                         _WinAPI_DrawText($hDC, "Times", $tRect, $aTextFormatting[1])                         _WinAPI_SetTextColor($hDC, 0x00FF00)                         _WinAPI_SelectObject($hDC, $aFont[1])                         DllStructSetData($iSubItmRect, 2, $aSubItmRect[1] + $aRectMargins[1] + 26)                         _WinAPI_DrawText($hDC, "Tahoma", $tRect, $aTextFormatting[1])                         _WinAPI_SetTextColor($hDC, 0xFF0000)                         _WinAPI_SelectObject($hDC, $aFont[2])                         DllStructSetData($iSubItmRect, 2, $aSubItmRect[1] + $aRectMargins[1] + 48)                         _WinAPI_DrawText($hDC, "Comic Sans", $tRect, $aTextFormatting[1])                         _WinAPI_SelectObject($hDC, $hFontOld)                         _WinAPI_SetTextColor($hDC, $iColPrev)                     Else                         _WinAPI_DrawText($hDC, $iSubItmText, $tRect, $aTextFormatting[$i])                     EndIf             EndSwitch         EndIf     Next EndFunc   ;==>__WM_DRAWITEM_ListView Func WM_MEASUREITEM($hWnd, $Msg, $wParam, $lParam)     Local $tMEASUREITEMS = DllStructCreate("uint cType;uint cID;uint itmID;uint itmW;uint itmH;ulong_ptr itmData", $lParam)     If DllStructGetData($tMEASUREITEMS, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG     DllStructSetData($tMEASUREITEMS, "itmH", $iListView_row_height) ; row height     Return 1 EndFunc   ;==>WM_MEASUREITEM ; Based on File to Base64 String Code Generator ; by UEZ ; <a href='http://www.autoitscript.com/forum/topic/...ng-code-generator-v103-build-2' class='bbc_url' title=''>http://www.autoitscript.com/forum/topic/...ng-code-generator-v103-build-2</a> ;====================================================================================== ; Function Name:        Load_BMP_From_Mem ; Description:  Loads an image which is saved as a binary string and converts it to a bitmap or hbitmap ; ; Parameters:       $bImage:    the binary string which contains any valid image which is supported by GDI+ ; Optional: $hHBITMAP:  if false a bitmap will be created, if true a hbitmap will be created ; ; Remark:           hbitmap format is used generally for GUI internal images, $bitmap is more a GDI+ image format ;                   Don't forget _GDIPlus_Startup() and _GDIPlus_Shutdown() ; ; Requirement(s):   GDIPlus.au3, Memory.au3 and _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Return Value(s):  Success: handle to bitmap (GDI+ bitmap format) or hbitmap (WinAPI bitmap format), ;                   Error: 0 ; Error codes:  1: $bImage is not a binary string ;                   2: unable to create stream on HGlobal ;                   3: unable to create bitmap from stream ; ; Author(s):            UEZ ; Additional Code:  thanks to progandy for the MemGlobalAlloc and tVARIANT lines and ;                   Yashied for _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3 ; Version:      v0.97 Build 2012-01-04 Beta ;======================================================================================= Func _Load_BMP_From_Mem($bImage, $hHBITMAP = False)     If Not IsBinary($bImage) Then Return SetError(1, 0, 0)     Local $aResult     Local Const $memBitmap = Binary($bImage) ;load image  saved in variable (memory) and convert it to binary     Local Const $len = BinaryLen($memBitmap) ;get length of image     Local Const $hData = _MemGlobalAlloc($len, $GMEM_MOVEABLE) ;allocates movable memory  ($GMEM_MOVEABLE = 0x0002)     Local Const $pData = _MemGlobalLock($hData) ;translate the handle into a pointer     Local $tMem = DllStructCreate("byte[" & $len & "]", $pData) ;create struct     DllStructSetData($tMem, 1, $memBitmap) ;fill struct with image data     _MemGlobalUnlock($hData) ;decrements the lock count  associated with a memory object that was allocated with GMEM_MOVEABLE     $aResult = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "handle", $pData, "int", True, "ptr*", 0) ;Creates a stream object that uses an HGLOBAL memory handle to store the stream contents     If @error Then SetError(2, 0, 0)     Local Const $hStream = $aResult[3]     $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromStream", "ptr", $hStream, "int*", 0) ;Creates a Bitmap object based on an IStream COM interface     If @error Then SetError(3, 0, 0)     Local Const $hBitmap = $aResult[2]     Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr")     DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, _             "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;release memory from $hStream to avoid memory leak     $tMem = 0     $tVARIANT = 0     If $hHBITMAP Then         Local Const $hHBmp = _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)         _GDIPlus_BitmapDispose($hBitmap)         Return $hHBmp     EndIf     Return $hBitmap EndFunc   ;==>_Load_BMP_From_Mem Func _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)     Local $tBIHDR, $Ret, $tData, $pBits, $hResult = 0     $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)     If (@error) Or ($Ret[0]) Then Return 0     $tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Ret[2], $Ret[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)     $pBits = DllStructGetData($tData, 'Scan0')     If Not $pBits Then Return 0     $tBIHDR = DllStructCreate('dword;long;long;ushort;ushort;dword;dword;long;long;dword;dword')     DllStructSetData($tBIHDR, 1, DllStructGetSize($tBIHDR))     DllStructSetData($tBIHDR, 2, $Ret[2])     DllStructSetData($tBIHDR, 3, $Ret[3])     DllStructSetData($tBIHDR, 4, 1)     DllStructSetData($tBIHDR, 5, 32)     DllStructSetData($tBIHDR, 6, 0)     $hResult = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBIHDR), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'dword', 0)     If (Not @error) And ($hResult[0]) Then         DllCall('gdi32.dll', 'dword', 'SetBitmapBits', 'ptr', $hResult[0], 'dword', $Ret[2] * $Ret[3] * 4, 'ptr', DllStructGetData($tData, 'Scan0'))         $hResult = $hResult[0]     Else         $hResult = 0     EndIf     _GDIPlus_BitmapUnlockBits($hBitmap, $tData)     Return $hResult EndFunc   ;==>_GDIPlus_BitmapCreateDIBFromBitmap Func _Decompress_Binary_String_to_Bitmap($Base64String)     $Base64String = Binary($Base64String)     Local $iSize_Source = BinaryLen($Base64String)     Local $pBuffer_Source = _WinAPI_CreateBuffer($iSize_Source)     DllStructSetData(DllStructCreate('byte[' & $iSize_Source & ']', $pBuffer_Source), 1, $Base64String)     Local $pBuffer_Decompress = _WinAPI_CreateBuffer(8388608)     Local $Size_Decompressed = _WinAPI_DecompressBuffer($pBuffer_Decompress, 8388608, $pBuffer_Source, $iSize_Source)     Local $b_Result = Binary(DllStructGetData(DllStructCreate('byte[' & $Size_Decompressed & ']', $pBuffer_Decompress), 1))     _WinAPI_FreeMemory($pBuffer_Source)     _WinAPI_FreeMemory($pBuffer_Decompress)     Return $b_Result EndFunc   ;==>_Decompress_Binary_String_to_Bitmap Func _Icon_Image_Checkbox_Unchecked()     Local $Base64String     $Base64String &= '7rBIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAANfc3ADZ3t4AANvg4ADe4uIAAOLl5QDl6OgAAOns7ADs7+8AAO/x8QDx8/MAAPT19QD29/cAAPj5+QD6+/sAAPz9/QD+/v7wAP///xNc/wB/AD8A/z8APwA/AD8APwA/AD8ACAAb4HYLAAEJAOEBCgsMAA0ODxAREhISbeIBCQcC4gEIBwLiAQfbBwLiAQYHAuIBBQcC4gG2BAcC4gEDBwLiAQIHAv/jAQcC5AEGAuIB7BceAOCfHgN/AG0A4QZhAA=='     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Unchecked Func _Icon_Image_Checkbox_Checked()     Local $Base64String     $Base64String &= 'z7BIAAABABAQEAFwCAAAaAUAABYAAMwAKAAYAJAAIAAYAVwZAQBAAQIYDgCAgAAAAISEhADe3t5AAN7n5wDnAQbvCO8A7wEG9/cA9/EABv///xN4/wE/AD8A/z8APwA/AD8AHwAMAOB6CwAGAQkA4QEHCAkJCR4KAgDjAQcC5AEHCAKDAwLiAQYHBwICAwI54gEFBsABAwLjAQUCxgIkBOIBBAUCRQbjAVgEBQUCAuQBAwUCCPPkAQUCBwjkAQYC4gHsF3seAOCfA38AbQDhBmEA'     Return _Decompress_Binary_String_to_Bitmap(_Base64Decode($Base64String)) EndFunc   ;==>_Icon_Image_Checkbox_Checked Func _Base64Decode($input_string)     Local $struct = DllStructCreate("int")     Local $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", 0, "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(1, 0, "")     Local $a = DllStructCreate("byte[" & DllStructGetData($struct, 1) & "]")     $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", "str", $input_string, "int", 0, "int", 1, "ptr", DllStructGetPtr($a), "ptr", DllStructGetPtr($struct, 1), "ptr", 0, "ptr", 0)     If @error Or Not $a_Call[0] Then Return SetError(2, 0, "")     Return DllStructGetData($a, 1) EndFunc   ;==>_Base64Decode

Edited by rover, 19 April 2012 - 06:35 PM.

  • footswitch likes this
I see fascists...

#16 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 19 April 2012 - 08:31 AM

@rover
What kind of sourcery is this??!? ;)

Posted Image

Once again, thank you thank you thank you.

#17 rover

rover

    unmutual

  • Active Members
  • PipPipPipPipPipPip
  • 825 posts

Posted 19 April 2012 - 09:16 AM

One more thing

Your timing is good...

This example is more relevant to your questions regarding the Outlook multiline listview.

To get two or more fonts per line (in this case normal and bold) DrawText is called twice per line.
Draw the left most text, set the left rect element to the width of the leftmost text plus a few added pixels to indent, then draw the right most text.

Text metrics measuring code is needed to replace the hard coded values used for setting left rect and top rect GetStringWidth code added for left rect

The number of drawtext calls can be cut down by using multiline text with linefeeds,
but then you can't set indentation and font colour/bold per line

The example is optimized for speed with dll pseudo handles for dllcalls, stripped down/optimized listview functions and global resources (fonts/pens/brush)
for re-use in the WM_DRAWITEM message handler

Edit: added _GUICtrlListView_GetStringWidth
Edit: corrected ODS_SELECTED multiple item selection, added optional themed/unthemed custom coloured select bar demonstration (try the listview states in Vista/Win7),
closed theme handle, added themes parts and states usage example, added optional remove line separators when item selection themed, clarified a few things

Edit: Added combo for Button or *Listview theme parts, Added resize of theme rect for Listview parts
*Listview group header theme has a better gradient than button in Vista+

AutoIt         
;coded by rover 2k12 #include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #include <FontConstants.au3> Opt("GUIDataSeparatorChar", "|") Global Const $ODA_SELECT = 0x2 Global Const $ODA_FOCUS = 0x4 Global Const $ODS_SELECTED = 0x0001 Global Const $ODT_LISTVIEW = 102 Global Const $ODA_DRAWENTIRE = 0x1 Global $iDllGDI = DllOpen("gdi32.dll") Global $iDllUSER32 = DllOpen("user32.dll") Global $iDllUxtheme = DllOpen("uxtheme.dll") ;global resources for WM_DRAWITEM - optimize speed Global $aFont[2] $aFont[0] = _WinAPI_CreateFont(16, 0, 0, 0, $FW_HEAVY, False, False, False, _         $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, 'Calibri') $aFont[1] = _WinAPI_CreateFont(16, 0, 0, 0, $FW_MEDIUM, False, False, False, _         $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, 'Calibri') Global $hPen1 = _WinAPI_CreatePen($PS_SOLID, 1, 0xF3EAE7) Global $hPen2 = _WinAPI_CreatePen($PS_SOLID, 1, 0xF4E8E6) Global $hBrush = _WinAPI_CreateSolidBrush(0xEEDDBB) ;Theme Parts and States ;<a href='http://msdn.microsoft.com/en-us/library/windows/desktop/bb773210%28v=vs.85%29.aspx' class='bbc_url' title='External link' rel='nofollow external'>http://msdn.microsoft.com/en-us/library/windows/desktop/bb773210%28v=vs.85%29.aspx</a> ;Part - vsstyle.h Global Const $BP_PUSHBUTTON = 1 Global Const $LVP_GROUPHEADER = 6 ;State - vsstyle.h Global Enum $PBS_NORMAL=1,$PBS_HOT,$PBS_PRESSED,$PBS_DISABLED,$PBS_DEFAULTED Global Enum $LVGH_CLOSEHOT=10,$LVGH_CLOSESELECTED,$LVGH_CLOSESELECTEDHOT,$LVGH_CLOSESELECTEDNOTFOCUSED ;this allows you to theme individual items for your own needs, not just if items are selected ;the same as customdrawing item and subitem colours ;XP+ Global $sTheme = 'Button' Global $iThemePart = $BP_PUSHBUTTON Global $iThemeState = $PBS_NORMAL ; Vista+ ;Global $sTheme = 'Listview' ;Global $iThemePart = $LVP_GROUPHEADER ;Global $iThemeState = $LVGH_CLOSEMIXEDSELECTION Global $hTheme = DllCall($iDllUxtheme, 'ptr', 'OpenThemeData', 'hwnd', 0, 'wstr', $sTheme) $hTheme = $hTheme[0] ;global structs for WM_DRAWITEM - optimize speed ;rect, text buffer and LVITEM structures Global $tLVRect = DllStructCreate($tagRECT) Global $tLVText = DllStructCreate("wchar[4096]") Global $tLVITEM = DllStructCreate($tagLVITEM) Global $pLVITEM = DllStructGetPtr($tLVITEM) DllStructSetData($tLVITEM, "TextMax", 4096) DllStructSetData($tLVITEM, "SubItem", 0) DllStructSetData($tLVITEM, "Text", DllStructGetPtr($tLVText)) ; WM_MEASUREITEM allows setting the row height Global $iListView_row_height = 130 Global $hListView ;must be declared before listview created GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM") ; place before listview creation - message sent once for each ownerdrawn control created GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") ;placed here, WM_MEASUREITEM can now be unregistered in the handler (deleting or adding items after unregistering maintains row height setting this way) ; --------------------------------------------------- $hGUI = GUICreate("Ownerdrawn multiline ListView", 324, 425) $cListView = GUICtrlCreateListView("", 2, 2, 320, 268, BitOR($LVS_REPORT, $LVS_NOCOLUMNHEADER, $LVS_OWNERDRAWFIXED, $LVS_SHOWSELALWAYS)) $hListView = GUICtrlGetHandle($cListView) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT)) ;double buffer improves performance _GUICtrlListView_AddColumn($hListView, "", 298) Global $aTextHdr[4] = ["From:", "Sent:", "To:", "Subject:"] For $row = 1 To 10     _GUICtrlListView_AddItem($hListView, "Rover - AutoIt Forums|Thursday, April 19, 2012 05:0" & $row - 1 & "AM|footswitch|Re: Multiline listview like Outlook|" & _             "This is a rough mock-up of that Outlook listview" & @CRLF & "You will need to add code for the text metrics") Next ;adjust listview size for number of items shown - for efficient painting and to eliminate issue of a click on bottom item causing a jump to next item Local $iY = _GUICtrlListView_ApproximateViewHeight($hListView, _GUICtrlListView_GetCounterPage($hListView)) GUICtrlSetPos($cListView, 2, 2, 320, $iY + 4) Global $cSelect = GUICtrlCreateButton("Themed Select", 2, $iY + 8, 120, 23) Global $cTheme = GUICtrlCreateCombo("Button", 120+2, $iY + 9, 60) GUICtrlSetData(-1, "Listview", "Button") Global $cState = GUICtrlCreateCombo("1 NORMAL", 180+4, $iY + 9, 80) GUICtrlSetData(-1, "2 HOT|3 PRESSED|4 GREYED|5 DEFAULT", "1 NORMAL") Global $cLabel =  GUICtrlCreateLabel("Select Item"&@CRLF&"Style", 260+8, $iY + 8) GUISetState() ; Loop until user exits While 1     Switch GUIGetMsg()         Case $GUI_EVENT_CLOSE             ExitLoop         Case $cTheme             DllCall($iDllUxtheme, 'uint', 'CloseThemeData', 'ptr', $hTheme)             Switch GUICtrlRead($cTheme)                 Case "Button"                     $sTheme = "Button"                     $iThemePart = $BP_PUSHBUTTON                     GUICtrlSetData($cState, "|1 NORMAL|2 HOT|3 PRESSED|4 GREYED|5 DEFAULT", "1 NORMAL")                 Case "Listview"                     $sTheme = "Listview"                     $iThemePart = $LVP_GROUPHEADER                     GUICtrlSetData($cState, "|10|11|12|13", "11")             EndSwitch             $hTheme = DllCall($iDllUxtheme, 'ptr', 'OpenThemeData', 'hwnd', 0, 'wstr', GUICtrlRead($cTheme))             $hTheme = $hTheme[0]             $iThemeState = Number(StringLeft(GUICtrlRead($cState), 2))             _WinAPI_InvalidateRect($hListView)         Case $cState             $iThemeState = Number(StringLeft(GUICtrlRead($cState), 2))             _WinAPI_InvalidateRect($hListView)         Case $cSelect             If Not $hTheme Then                 GUICtrlSetData($cSelect, "Themed Select")                 $hTheme = DllCall($iDllUxtheme, 'ptr', 'OpenThemeData', 'hwnd', 0, 'wstr', $sTheme)                 $hTheme = $hTheme[0]             Else                 GUICtrlSetData($cSelect, "Unthemed Select")                 DllCall($iDllUxtheme, 'uint', 'CloseThemeData', 'ptr', $hTheme)                 $hTheme = 0             EndIf             _WinAPI_InvalidateRect($hListView)     EndSwitch WEnd GUIDelete() DllCall($iDllUxtheme, 'uint', 'CloseThemeData', 'ptr', $hTheme) _WinAPI_DeleteObject($hPen1) _WinAPI_DeleteObject($hPen2) _WinAPI_DeleteObject($hBrush) For $i = 0 To UBound($aFont) - 1     If $aFont[$i] Then _WinAPI_DeleteObject($aFont[$i]) Next Exit Func WM_MEASUREITEM($hWnd, $Msg, $wParam, $lParam)     Local $tMEASUREITEMS = DllStructCreate("uint cType;uint cID;uint itmID;uint itmW;uint itmH;ulong_ptr itmData", $lParam)     If DllStructGetData($tMEASUREITEMS, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG     DllStructSetData($tMEASUREITEMS, "itmH", $iListView_row_height) ; row height     GUIRegisterMsg($WM_MEASUREITEM, "") ; unregister message handler call this after last ownerdrawn listview created - message no longer sent     Return 1 EndFunc   ;==>WM_MEASUREITEM Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)     Local $tDRAWITEMSTRUCT, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC     $tDRAWITEMSTRUCT = DllStructCreate( _             "uint cType;" & _             "uint cID;" & _             "uint itmID;" & _             "uint itmAction;" & _             "uint itmState;" & _             "hwnd hItm;" & _             "handle hDC;" & _             "long itmRect[4];" & _             "ulong_ptr itmData" _             , $lParam)     If DllStructGetData($tDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG     $cID = DllStructGetData($tDRAWITEMSTRUCT, "cID")     $itmID = DllStructGetData($tDRAWITEMSTRUCT, "itmID")     $itmAction = DllStructGetData($tDRAWITEMSTRUCT, "itmAction")     $itmState = DllStructGetData($tDRAWITEMSTRUCT, "itmState")     $hItm = DllStructGetData($tDRAWITEMSTRUCT, "hItm")     $hDC = DllStructGetData($tDRAWITEMSTRUCT, "hDC")     Switch $cID ; will look for ControlID, not window handle.         Case $cListView             Switch $itmAction             Case $ODA_DRAWENTIRE                     __WM_DRAWITEM_ListView($hItm, $tDRAWITEMSTRUCT, $cID, $itmID, $itmAction, $itmState, $hDC)             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_DRAWITEM Func __WM_DRAWITEM_ListView(ByRef $hLV, ByRef $tDRAWITEMSTRUCT, ByRef $cID, ByRef $itmID, ByRef $itmAction, ByRef $itmState, ByRef $hDC)     Local $iTxtCol, $bSelected = BitAND($itmState, $ODS_SELECTED), $iTextFormatting = BitOR($DT_LEFT, $DT_WORDBREAK)     If Not $bSelected Then         $iTxtCol = 0xB79588     Else ;selected         $iTxtCol = 0x494949         ;Theme Parts and States         ;<a href='http://msdn.microsoft.com/en-us/library/windows/desktop/bb773210%28v=vs.85%29.aspx' class='bbc_url' title='External link' rel='nofollow external'>http://msdn.microsoft.com/en-us/library/windows/desktop/bb773210%28v=vs.85%29.aspx</a>         Local $pItemRect = DllStructGetPtr($tDRAWITEMSTRUCT, "itmRect")         If $hTheme Then             If $sTheme = "Listview" Then                 Local $tItemRect = DllStructCreate($tagRect, $pItemRect)                     DllStructSetData($tItemRect, 1, DllStructGetData($tItemRect, 1)+1)                     DllStructSetData($tItemRect, 2, DllStructGetData($tItemRect, 2)+1)                     DllStructSetData($tItemRect, 3, DllStructGetData($tItemRect, 3)-1)                     DllStructSetData($tItemRect, 4, DllStructGetData($tItemRect, 4)-1)                 $pItemRect = DllStructGetPtr($tItemRect)             EndIf             DllCall($iDllUxtheme, 'uint', 'DrawThemeBackground', 'ptr', $hTheme, 'hwnd', $hDC, 'int', $iThemePart, 'int', $iThemeState, 'ptr', $pItemRect, 'ptr', 0)         Else             DllCall($iDllUSER32, "int", "FillRect", "handle", $hDC, "ptr", DllStructGetPtr($tDRAWITEMSTRUCT, "itmRect"), "handle", $hBrush)         EndIf     EndIf     GUICtrlSendMsg($cID, $LVM_GETITEMTEXTW, $itmID, $pLVITEM)     Local $aSubItmText = StringSplit(DllStructGetData($tLVText, 1), "|", 2)     DllStructSetData($tLVText, 1, "")     DllStructSetData($tLVRect, "Top", 0)     DllStructSetData($tLVRect, "Left", $LVIR_BOUNDS)     GUICtrlSendMsg($cID, $LVM_GETSUBITEMRECT, $itmID, DllStructGetPtr($tLVRect))     Local $iLeft = DllStructGetData($tLVRect, 1) + 6 ;Left     Local $iTop = DllStructGetData($tLVRect, 2) ;Top     DllStructSetData($tLVRect, 1, $iLeft) ;Left     Switch $hLV         Case $hListView             Local $iColPrev = __WinAPI_SetTextColor($hDC, 0x000000) ;save previous font and text colour             Local $hFontOld = __WinAPI_SelectObject($hDC, $aFont[0]) ;Bold             ;------------------------------------------------------------             ;multiline, but no per line indentation or colour             ;DllStructSetData($tLVRect, 2, $iTop+2)             ;__WinAPI_DrawText($hDC, "From:"&@CRLF&"Sent:"&@CRLF&"To:"&@CRLF&"Subject:", $tLVRect, $iTextFormatting)             ;------------------------------------------------------------             DllStructSetData($tLVRect, 2, $iTop + 2)             __WinAPI_DrawText($hDC, $aTextHdr[0], $tLVRect, $iTextFormatting)             DllStructSetData($tLVRect, 2, $iTop + 20)             __WinAPI_DrawText($hDC, $aTextHdr[1], $tLVRect, $iTextFormatting)             DllStructSetData($tLVRect, 2, $iTop + 38)             __WinAPI_DrawText($hDC, $aTextHdr[2], $tLVRect, $iTextFormatting)             DllStructSetData($tLVRect, 2, $iTop + 56)             __WinAPI_DrawText($hDC, $aTextHdr[3], $tLVRect, $iTextFormatting)             __WinAPI_SelectObject($hDC, $aFont[1]) ;Normal             ;------------------------------------------------------------             ;multiline, but no per line indentation or colour             ;__WinAPI_SetTextColor($hDC, 0x494949)             ;DllStructSetData($tLVRect, 1, $iLeft+50)             ;DllStructSetData($tLVRect, 2, $iTop+2)             ;__WinAPI_DrawText($hDC, $aSubItmText[0]&@CRLF&$aSubItmText[1]&@CRLF&$aSubItmText[2]&@CRLF&$aSubItmText[3], $tLVRect, $iTextFormatting)             ;------------------------------------------------------------             __WinAPI_SetTextColor($hDC, 0xFF0000)             DllStructSetData($tLVRect, 1, $iLeft + __GUICtrlListView_GetStringWidth($cID, $aTextHdr[0]) + 5)             DllStructSetData($tLVRect, 2, $iTop + 2)             __WinAPI_DrawText($hDC, $aSubItmText[0], $tLVRect, $iTextFormatting)             __WinAPI_SetTextColor($hDC, 0x494949)             DllStructSetData($tLVRect, 1, $iLeft + __GUICtrlListView_GetStringWidth($cID, $aTextHdr[1]) + 5)             DllStructSetData($tLVRect, 2, $iTop + 20)             __WinAPI_DrawText($hDC, $aSubItmText[1], $tLVRect, $iTextFormatting)             DllStructSetData($tLVRect, 1, $iLeft + __GUICtrlListView_GetStringWidth($cID, $aTextHdr[2]) + 5)             DllStructSetData($tLVRect, 2, $iTop + 38)             __WinAPI_DrawText($hDC, $aSubItmText[2], $tLVRect, $iTextFormatting)             DllStructSetData($tLVRect, 1, $iLeft + __GUICtrlListView_GetStringWidth($cID, $aTextHdr[3]) + 5)             DllStructSetData($tLVRect, 2, $iTop + 56)             __WinAPI_DrawText($hDC, $aSubItmText[3], $tLVRect, $iTextFormatting)             __WinAPI_SetTextColor($hDC, $iTxtCol)             DllStructSetData($tLVRect, 1, $iLeft + 2)             DllStructSetData($tLVRect, 2, $iTop + 80)             __WinAPI_DrawText($hDC, $aSubItmText[4], $tLVRect, $iTextFormatting)             If $bSelected And $hTheme Then Return ;optional - don't paint lines when item selected - in this example only for benefit of themed selected items             Local $obj_orig = __WinAPI_SelectObject($hDC, $hPen1)             __WinAPI_DrawLine($hDC, $iLeft, DllStructGetData($tLVRect, 4) - 2, 320 - ($iLeft * 2) - 16, DllStructGetData($tLVRect, 4) - 2)             __WinAPI_SelectObject($hDC, $hPen2)             __WinAPI_DrawLine($hDC, $iLeft, DllStructGetData($tLVRect, 4) - 3, 320 - ($iLeft * 2) - 16, DllStructGetData($tLVRect, 4) - 3)             __WinAPI_SelectObject($hDC, $obj_orig)             ;__WinAPI_SelectObject($hDC, $hFontOld)             ;__WinAPI_SetTextColor($hDC, $iColPrev)     EndSwitch     Return EndFunc   ;==>__WM_DRAWITEM_ListView Func __WinAPI_DrawLine($hDC, $iX1, $iY1, $iX2, $iY2)     DllCall($iDllGDI, "bool", "MoveToEx", "handle", $hDC, "int", $iX1, "int", $iY1, "ptr", 0)     If @error Then Return SetError(@error, @extended, False)     DllCall($iDllGDI, "bool", "LineTo", "handle", $hDC, "int", $iX2, "int", $iY2)     If @error Then Return SetError(@error, @extended, False)     Return True EndFunc   ;==>__WinAPI_DrawLine Func __WinAPI_DrawText(ByRef $hDC, $sText, ByRef $tRect, ByRef $iFlags)     DllCall($iDllUSER32, "int", "DrawTextW", "hwnd", $hDC, "wstr", $sText, "int", StringLen($sText), "struct*", $tRect, "int", $iFlags) EndFunc   ;==>__WinAPI_DrawText Func __WinAPI_SetTextColor($hDC, $iColor)     Local $aResult = DllCall($iDllGDI, "INT", "SetTextColor", "handle", $hDC, "dword", $iColor)     If @error Then Return SetError(@error, @extended, -1)     Return $aResult[0] EndFunc   ;==>__WinAPI_SetTextColor Func __WinAPI_SelectObject($hDC, $hGDIObj)     Local $aResult = DllCall($iDllGDI, "handle", "SelectObject", "handle", $hDC, "handle", $hGDIObj)     If @error Then Return SetError(@error, @extended, False)     Return $aResult[0] EndFunc   ;==>__WinAPI_SelectObject Func __GUICtrlListView_GetStringWidth($hWnd, $sString)     Local $tBuffer = DllStructCreate("wchar Text[" & StringLen($sString) + 1 & "]")     DllStructSetData($tBuffer, "Text", $sString)     Local $iRet = GUICtrlSendMsg($hWnd, $LVM_GETSTRINGWIDTHW, 0, DllStructGetPtr($tBuffer))     Return $iRet EndFunc   ;==>__GUICtrlListView_GetStringWidth

Edited by rover, 19 April 2012 - 10:09 PM.

  • footswitch, UEZ, KaFu and 1 other like this
I see fascists...

#18 rover

rover

    unmutual

  • Active Members
  • PipPipPipPipPipPip
  • 825 posts

Posted 19 April 2012 - 09:43 AM

I've added _GUICtrlListView_GetStringWidth to the example
I see fascists...

#19 UEZ

UEZ

    Never say never

  • MVPs
  • 3,597 posts

Posted 19 April 2012 - 10:51 AM

Very nice examples rover! ;)

Br,
UEZ

 
The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯


#20 footswitch

footswitch

    Polymath

  • Active Members
  • PipPipPipPip
  • 206 posts

Posted 19 April 2012 - 11:27 AM

ahahahah that was exactly what I was trying to figure out ;)
your approach here is very interesting!




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users