Jump to content

DrJohn

Active Members
  • Posts

    44
  • Joined

  • Last visited

Everything posted by DrJohn

  1. Argh! I was a complete bonehead! I somehow never noticed that third parameter to _GUICtrlListView_AddItem() [0-based index of the item's icon in the control's image list]. How I managed not to see that, I can't imagine. I thought the assignment of an image to an item in the ListView was purely positional (the first item in the ListView gets the first image in the ImageList, the second item in the ListView gets the second item in the ImageList, and so on ...) There are none so blind as those who will not see. 😬 This pretty well explains it. Thanks @Dan_555! /John
  2. Hello all. It's me again. I've got a ListView with an associated ImageList to display icons. What I seem to be hung up on is how to keep the ImageList updated to match the ListView as the latter changes. I thought it was the case that the indices of the items in the ListView and those in the ImageList just needed to match. So, for example, if I: Delete an item from the ListView [_GUICtrlListView_DeleteItem()], and also delete the image at the matching index in the ImageList [_GUIImageList_Remove()]. Then add a new item to the end of the ListView [_GUICtrlListView_AddItem()], and correspondingly add an image at the end of the ImageList [_GUIImageList_AddIcon()] Shouldn't everything stay in sync? Here's the code I thought would work: #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <FontConstants.au3> #include <WindowsConstants.au3> #include <GuiImageList.au3> Test() func Test() $gui = GUICreate("Test", 400, 300) ; Create ListView $lv = _GUICtrlListView_Create($gui, "", 10, 10, 380, 240, $LVS_DEFAULT) _GUICtrlListView_AddColumn($lv, "Col1", 50) _GUICtrlListView_AddColumn($lv, "Col2", 50) for $i = 0 to 2 $s = StringFormat("%d,1", $i+1) _GUICtrlListView_AddItem($lv, $s, $i) $s = StringFormat("%d,2", $i+1) _GUICtrlListView_AddSubItem($lv, $i, $s, 1) next ; Add ImageList $img_list = _GUIImageList_Create(16, 16, 5, 3) for $i = 0 to 2 $ico = StringFormat("%d.ico", $i+1) _GUIImageList_AddIcon($img_list, $ico) next _GUICtrlListView_SetImageList($lv, $img_list, 1) ; $btn = GUICtrlCreateButton("Test", 10, 260, 60, 30) GUISetState(@SW_SHOW) HotKeySet("^q", Quit) ; Loop until the user exits. while True switch GUIGetMsg() case $GUI_EVENT_CLOSE Exit case $btn ; Remove 2nd list item and image _GUICtrlListView_DeleteItem($lv, 1) _GUIImageList_Remove($img_list, 1) ; Add new item to end of ListView $idx = _GUICtrlListView_AddItem($lv, "foo") _GUICtrlListView_AddSubItem($lv, $idx, "bar", 1) ; Add new image to end of ImageList _GUIImageList_AddIcon($img_list, "5.ico") endswitch wend GUIDelete() endfunc func Quit() Exit endfunc What seems to happen is that when the new item is added to the ListView, its icon is 1.ico (the first item in the ImageList), rather than 5.ico (the newly added item that should be at the end of the ImageList). Or do I need to re-create the whole ImageList any time the ListView changes? A zip file is attached that contains the script and also the .ico files, for easier testing. Thanks! /John test.zip
  3. Well, it seems to work fine, and it wasn't hard to implement. So I guess I shouldn't knock it. Thanks again.
  4. Hi again Melba. It turns out I wasn't imagining it. The Adlib function was stopping when the GUI was displayed. But in whittling the script down for testing (and posting), I inadvertently eliminated the part that made it so. One of the ways I display the GUI is through the tray menu. I found this thread from 2011 (in which you participated): So now I know that an Adlib function is expected to stop when the tray menu is displayed. That said, what I'm seeing is that once the tray menu closes (and the GUI starts up), the Adlib function remains stopped, which surprises me. New version of script attached, which now includes all the relevant details. Run the script, then display the GUI with F11 -- the Adlib function continues running. Click on the system tray icon and select Configure, and the GUI displays -- but the Adlib function remains stopped until the GUI exits. By any chance, when the GUI is started from the tray menu, is it regarded as a child window of the tray menu? So that Windows thinks the tray menu is still open (in some sense) as long as the GUI is open? /John EDIT: I might have thought, then, that if I explicitly specified a parent window when creating the GUI, it might work. But it didn't. Seems if I call ShowConfigGUI() directly from the main script, rather than as a callback from TrayItemSetOnEvent(), then the Adlib function keeps running. So the solution is probably to have the tray menu callback signal to the main script to start up the GUI, rather than doing it itself. ANOTHER EDIT: Yes, that seems to be the way to go. What I would have liked to do is for the top level GUI (the one that gets minimized to the system tray) to have its own message loop, with a Dummy control that I could message from the tray menu callback. But that evidently requires the top level GUI to be visible (i.e., not @SW_HIDE). So that doesn't work. More prosaic way is for the tray menu callback to simply set a flag that the infinite loop in the main script detects, acts on, and resets. Not as elegant, but I'm pretty sure it will work. test.au3
  5. Argh! I swear I tried using an Adlib function, before I tried the Timer. I thought my observation was that the Adlib function didn't trigger while the other GUI was displayed. But yours obviously does, so either I didn't observe carefully enough, or I did it wrong. Evidently, I need to take a closer look. 🤦‍♂️ Thanks again, Melba. /John
  6. Here's what I have: Main program script starts up, then resides in system tray infinite looping. (I do this by calling GUICreate('parent'), which I saw in the forum somewhere at some point). Before going into infinite loop, main script creates a popup GUI to display memory usage, then sets a Timer to update that popup. At some point, on user input, main script creates another user GUI with which the user is intended to interact. The idea is that the timer is supposed to keep the popup GUI updated, even when the main script is suspended while the user GUI is displayed. And it works most of the time. But intermittently, when the user GUI starts up, it hangs. Attached is a pared-down prototype. It's configured so that hitting {F11} pops up the user GUI. If I start up the main script, then alternately hit {F11} and {Esc}, the user GUI alternately pops up and then disappears. But eventually (usually within 40 or 50 tries), it hangs unresponsive when it pops up. If I comment out line #24, on which the Timer is set, that doesn't happen. So that appears to be the source of the problem. I'm wondering if there is a somewhat straightforward reason as to why this is evidently fraught with peril. Timers are a bit of a mysterious beast (at least to me), and it may well be that the answer to the question is "That's crazy! You just shouldn't use a Timer that way", or the like. In any case, I expected it to work, so if I understood why it doesn't, I probably would learn something. Thanks again! /John test.au3
  7. Melba is obviously going to be a much better authority on this (as well as most anything else) than me. But I think (as it was explained to me) once having put your ListView under control of GUIListViewEx, anything you do that changes its contents must use a GUIListViewEx function. So populating the ListView with _GUICtrlListView_AddItem() won't work. You can add to the end of a GUIListViewEx-controlled ListView with _GUIListViewEx_InsertSpec($iLV, -1, ...). This works for me: #include <GuiConstantsEx.au3> #include <WindowsConstants.au3> #include "GUIListViewEx.au3" #include <Array.au3> ;Opt("GUIResizeMode", 1) ;0=no resizing, <1024 special resizing ;No effect Global $iCount_Left = 20, $iCount_Right = 20, $vData, $sMsg, $aLV_List_Left, $aLV_List_Right, $aRet, $iEditMode = 0 $hGUI = GUICreate("LVEx Example 1", 500, 430) $hListView_Right = _GUICtrlListView_Create($hGUI, "", 10, 20, 480, 400, BitOR($LVS_DEFAULT, $WS_BORDER)) _GUICtrlListView_SetExtendedListViewStyle($hListView_Right, $LVS_EX_FULLROWSELECT) _GUICtrlListView_AddColumn($hListView_Right, "Peter", 83) _GUICtrlListView_AddColumn($hListView_Right, "Paul", 83) _GUICtrlListView_AddColumn($hListView_Right, "Mary", 83) GUICtrlSetResizing ( $hListView_Right, 1) GUIRegisterMsg($WM_SIZE, "WM_SIZE") ;============================================================================= ; Initiate LVEx - use read content as array - count parameter set - red insert mark - drag image - move edit by click + headers editable $iLV_Right_Index = _GUIListViewEx_Init($hListView_Right, $aLV_List_Right, 1, 0xFF0000, True, 32) ; All columns editable - simple text selected on open _GUIListViewEx_SetEditStatus($iLV_Right_Index, 0) ; Register for sorting, dragging and editing _GUIListViewEx_MsgRegister() ;============================================================================= $vRet = _GUIListViewEx_EventMonitor($iEditMode) If @error Then MsgBox($MB_SYSTEMMODAL, "Error", "Event error: " & @error) EndIf GUISetState() ;============================================================================= For $i = 1 To $iCount_Right ; _GUICtrlListView_AddItem($hListView_Right, "Peter " & $i - 1) ; If Mod($i, 4) Then ; _GUICtrlListView_AddSubItem($hListView_Right, $i - 1, "Paul " & $i - 1, 1) ; EndIf ; _GUICtrlListView_AddSubItem($hListView_Right, $i - 1, "Mary " & $i - 1, 2) local $a = _ [ _ "Peter " & $i - 1, _ Mod($i, 4) ? "Paul " & $i - 1 : "", _ "Mary " & $i - 1 _ ] _GUIListViewEx_InsertSpec($iLV_Right_Index, -1, $a, False, True) Next ;============================================================================= $Count = _GUICtrlListView_GetItemCount($hListView_Right) ConsoleWrite($Count &@CRLF) For $c = 0 To $Count If $c < 5 Then _GUIListViewEx_SetColour($iLV_Right_Index, "0x000000;0xFFF2B3", $c, 0) _GUIListViewEx_SetColour($iLV_Right_Index, "0x000000;0xFFF2B3", $c, 1) _GUIListViewEx_SetColour($iLV_Right_Index, "0x000000;0xFFF2B3", $c, 2) ElseIf $c > 10 Then _GUIListViewEx_SetColour($iLV_Right_Index, "0x000000;0xB3E5FF", $c, 0) _GUIListViewEx_SetColour($iLV_Right_Index, "0x000000;0xB3E5FF", $c, 1) _GUIListViewEx_SetColour($iLV_Right_Index, "0x000000;0xB3E5FF", $c, 2) EndIf Next ;============================================================================= Local $WinCoords = WinGetPos($hGUI) WinMove($hGUI, '', $WinCoords[0], $WinCoords[1], 900, $WinCoords[3]) ;Enlarge GUI in width GUICtrlSetPos($hListView_Right, 10, 20, 570, 400) ;============================================================================= While 1 $Msg = GUIGetMsg() If $Msg = $GUI_EVENT_CLOSE Then Exit $vRet = _GUIListViewEx_EventMonitor($iEditMode) If @error Then MsgBox($MB_SYSTEMMODAL, "Error", "Event error: " & @error) EndIf Sleep(100) $GetItemTxt = _GUIListViewEx_GetLastSelItem($iLV_Right_Index) ConsoleWrite('$GetItemTxt:' & $GetItemTxt & @CRLF) WEnd ;============================================================================= Func WM_SIZE($hWnd, $Msg, $wParam, $lParam) Local $iWidth = BitAND($lParam, 0xFFFF) Local $iHeight = BitShift($lParam, 16) _WinAPI_MoveWindow($hListView_Right, 10, 10, $iWidth - 40, $iHeight - 40, True) ;_GUICtrlListView_SetColumn($hListView_Right, 2, "Item", $iWidth - 260) Return $GUI_RUNDEFMSG EndFunc Move the GUISetState() call after the ListView is populated, and it isn't so flicker-y. In fact, move it to just before the message loop, and it isn't flicker-y at all. /John
  8. Thanks @Melba23. That makes sense. It's good to know -- I can be on the lookout for it in the future. /John
  9. Update: So I did switch over to using GUICtrlCreateListView(). A couple of minor hitches, but nothing that was too big a deal, and it works fine. In the process, though, I discovered something that surprises me. In fact, it was one of the things I bumped up against when I first considered making the switch, that made me think it was going to be trouble. I use the following code to access the currently selected list item: $idx = _GUICtrlListView_GetSelectedIndices($lv) $s = _GUICtrlListView_GetItemText($lv, $idx) This fails, apparently because $idx is a string (which I realize I have asked for deliberately, by letting the second parameter to _GUICtrlListView_GetSelectedIndices() default). _GUICtrlListView_GetItemText() apparently wants an integer, because this works: $idx = Number(_GUICtrlListView_GetSelectedIndices($lv)) $s = _GUICtrlListView_GetItemText($lv, $idx) Two things about this surprise me. First, I thought AutoIt took care of conversion between strings and numbers fairly transparently, and one didn't have to worry about this sort of thing. I know I mostly haven't. The second thing that I think is weird is that I only see this problem when the ListView is created with GUICtrlCreateListView(). If it is created with _GUICtrlListView_Create(), both of the above code blocks work as expected. In my case, when I switched from _GUICtrlListView_Create() to GUICtrlCreateListView(), the code broke in many places, and I thought I was hosed. It turned out it was just this one minor thing. A script to demonstrate is attached. As is, the ListView is created with GUICtrlCreateListView(). Run it, select a row in the list, and hit the Test button. The _GUICtrlListView_GetItemText() call on line #43 fails, but the one on line #48 succeeds. Flip the commenting on lines #12 and #13 so that the ListView is created with _GUICtrlListView_Create(), and both lines #43 and #48 succeed. No current problem on my part. I just thought if anyone else was wrestling with this issue, the information might be helpful. /John test.au3
  10. > Wouldn't it be more simple to just revert to GUICtrlCreateListView? Yes. Emphatically. I actually looked into that, and decided it would be intractable. Because basically I didn't see the forest for the trees. Here's the explanation, for what it's worth. The way the code is now, I create and populate my ListView like this: _GUICtrlListView_Create() _GUICtrlListView_AddColumn() ... _GUICtrlListView_AddItem()/_GUICtrlListView_AddSubItem() Then when I want to operate on the selected ListView item: $index = _GUICtrlListView_GetSelectedIndices() _GUICtrlListView_GetItemText($listview, $index) My whole code base essentially operates by passing that $index around and using it to access the ListView item. I thought that if I created the ListView using GUICtrlCreateListView(), then I had to populate it with GUICtrlCreateListViewItem(), which seems to follow a different paradigm -- each ListView item gets its own ControlID, and you access by ControlID instead of by index. Not accessing by index was going to mess with a bunch of my code. But it seems I was wrong about that. Even if you use GUICtrlCreateListView() to create the ListView, you can still populate it with _GUICtrlListView_AddColumn() and _GUICtrlListView_AddItem()/SubItem(). And then you can access by index. So this is probably the way to go. I just needed to think outside the box a little. Thanks, @careca. /John
  11. This is a minor annoyance, but it's bugging me because I feel like there should be a way out of it, and I haven't found it. I've got a script with two ListView's. Early on, I decided to create them with the UDF function [_GUICtrlListView_Create()] instead of GUICtrlCreateListView(), because it seems to me that the UDF functions to populate and work with a ListView are just easier to use. Unfortunately, there isn't any UDF function to set the ListView font and font size. So I ended up using _WinAPI_CreateFont() and _WinAPI_SetFont() to do it. Which seems to work fine. Then I decided to make the ListView font and font size configurable. So I whipped up a font chooser GUI, which allows for selection of font style and size. In the GUI, when you choose a style and size, it displays a Label in that style/size so you can get a preview of what it will look like. So far so good. Then I set the ListView font with that style and size. And it doesn't match. The text in the ListView is much smaller than in the GUI preview Label. Because, apparently, when you set the font size for a GUI Label with GUICtrlSetFont(), you're specifying size in points. With _WinAPI_CreateFont(), the size is 'height of font' (in pixels, I assume). So then I thought ... I need to take a given font style and point size, and convert it to the appropriate height. Then the ListView text should match what the GUI preview Label showed. Here's what I came up with. First, use GDIPlus to create a font object of the given family and size: $hGraphic = _GDIPlus_GraphicsCreateFromHWND($g_GUI) $hFamily = _GDIPlus_FontFamilyCreate($family) $hFont = _GDIPlus_FontCreate($hFamily, $g_Size) Then, get its height: $height = _GDIPlus_FontGetHeight($hFont, $hGraphic) Then pass that height to _WinAPI_CreateFont(): $font_obj = _WinAPI_CreateFont( _ $height, 0, 0, 0, _ $FW_DONTCARE, False, False, False, _ $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, _ $PROOF_QUALITY, $DEFAULT_PITCH, _ $g_Style _ ) It almost works. But not quite. Attached is a test script that demonstrates. When you choose a font style and size, it displays two labels. The first is set to the chosen point size. The second is set with _WinAPI_CreateFont() using a height obtained by the method I describe. In the case of some fonts (on my system, at least), the two effectively look identical. In other cases, not so much. (The difference shows particularly well for Trebuchet MS, and any of the Montserrat font styles, which I think are present on most Windows systems? Especially at larger sizes). Ought this not to work? Or is there another way I can convert point size to appropriate height to pass to _WinAPI_CreateFont() so it matches? Thanks! /John font_enum.au3
  12. Hi again Melba. I think I may have found a bug. Although I wouldn't bet the farm (even if I had one) that it's not something I'm doing wrong. _GUIListViewEx_InsertSpec() doesn't seem to handle the case where GUIDataSeparatorChar is set to something other than the default "|". This only happens when the original ListView is created with GUICtrlCreateListView(), not if it is created with _GUICtrlListView_Create(). Attached is a script that demonstrates. Steps to reproduce: Ensure that the Opt("GUIDataSeparatorChar", Chr(31)) statement on line #7 is not commented out Ensure that line #99 is commented out, and line #100 is not, so that the ListView is created with GUICtrlCreateListView() Run script Click on the New button (Similar problem occurs if you drag and drop -- I presume because that uses _GUIListViewEx_InsertSpec() also?) Switch out line #99 for line #100, and it works as expected. /John Addendum: Seems to be happier if I replace "|" on line #5225 of GUIListViewEx.au3 with Opt("GUIDataSeparatorChar"). Wouldn't presume I could safely change the file myself, though, other than for testing purposes. test.au3
  13. Sure thing. I don't think it's rocket science, but if it would be helpful ... Here's a sample script that creates a Font Family/Style/Size chooser GUI. EnumFontTree() uses _WinAPI_EnumFontFamilies() to gather a list of all installed font families (this particular version leaves out those beginning with "@"), and organizes it into a tree of families and associated sub-families. The funny business happens on lines 130-131 -- any font families in the initial return list that start with the same 'stem' (prefix) get grouped together as associated 'sub-families' Then when EnumFontStyles() enumerates the styles for a given family, it includes both those obtained by calling _WinAPI_EnumFontFamilies() on that family, plus any 'sub-families' that were collected in the initial pass. (The rest of the code is just dedicated to creating and managing the three combo boxes). The result is similar to _ChooseFont(), but not identical. Note, for example, that if you select Cambria from the Family list, the Styles list populates with Cambria, Cambria Bold, Cambria Bold Italic, Cambria Italic ... and Cambria Math. _ChooseFont() doesn't do this. My code groups Cambria Math together with the others because the name begins with the same 'stem'. _ChooseFont() doesn't because ... I don't know why. #include <GuiConstantsEx.au3> #include <WinAPIGdi.au3> #include <FontConstants.au3> #include <WindowsConstants.au3> #include <GuiComboBox.au3> #include <Array.au3> Main() ; -------------------------------------------------------------------------- func Main() $gui = GUICreate("FontEnum", 800, 600) GUISetState(@SW_SHOW, $gui) $cur_font = "Arial Bold" $cur_size = 12 $family_combo = GUICtrlCreateCombo _ ( _ "", _ 10, 10, _ 250, 300, _ BitOR($CBS_SIMPLE, $WS_VSCROLL) _ ) $style_combo = GUICtrlCreateCombo _ ( _ "", _ 270, 10, _ 250, 200, _ BitOR($CBS_SIMPLE, $WS_VSCROLL) _ ) $size_combo = GUICtrlCreateCombo("", 530, 10, 100, 20) GUICtrlSetData _ ( _ $size_combo, _ "8|9|10|11|12|13|14|16|18|20|22|24|26|28|30|32|36|42|48", _ $cur_size _ ) $sample_label = GUICtrlCreateLabel($cur_font, 10, 320, 780, 100) GUICtrlSetFont($sample_label, $cur_size, $FW_DONTCARE, $GUI_FONTNORMAL, $cur_font) $font_tree = EnumFontTree() PopulateComboBoxes($font_tree, $family_combo, $style_combo, $cur_font) while True $msg = GUIGetMsg() switch $msg case $family_combo, $style_combo, $size_combo if ($msg = $family_combo) then PopulateStylesComboBox($font_tree, $family_combo, $style_combo, "") endif $cur_font = GUICtrlRead($style_combo) $cur_size = GUICtrlRead($size_combo) GUICtrlSetFont _ ( _ $sample_label, _ $cur_size, _ $FW_DONTCARE, _ $GUI_FONTNORMAL, _ $cur_font _ ) GUICtrlSetData($sample_label, $cur_font) case $GUI_EVENT_CLOSE Exit endswitch wend endfunc ; -------------------------------------------------------------------------- func PopulateComboBoxes($ft, $f, $st, $sel) for $i from 0 to ubound($ft) - 1 $family = $ft[$i][0] _GUICtrlComboBox_AddString($f, $family) if (($sel <> "") and (StringLeft($sel, StringLen($family)) = $family)) then _GUICtrlComboBox_SetCurSel($f, $i) PopulateStylesComboBox($ft, $f, $st, $sel) endif next endfunc ; -------------------------------------------------------------------------- func PopulateStylesComboBox($ft, $f, $st, $sel) _GUICtrlComboBox_ResetContent($st) $styles = EnumFontStyles($ft, GUICtrlRead($f)) for $i from 0 to ubound($styles) - 1 $style = $styles[$i] _GUICtrlComboBox_AddString($st, $style) if (($sel <> "") and ($style = $sel)) then _GUICtrlComboBox_SetCurSel($st, $i) else _GUICtrlComboBox_SetCurSel($st, 0) endif next endfunc ; -------------------------------------------------------------------------- func EnumFontTree() local $font_list = _WinAPI_EnumFontFamilies(0, "", $ANSI_CHARSET, -1, "@*", True) _ArraySort($font_list, 0, 1, 0, 0) local $font_tree[0][2] $i = 1 while ($i <= $font_list[0][0]) $stem = $font_list[$i][0] _ArrayAdd($font_tree, $stem) local $sub[0] do $i += 1 if ($i > $font_list[0][0]) then ExitLoop $st = $font_list[$i][0] if (StringLeft($st, StringLen($stem)) <> $stem) then ExitLoop _ArrayAdd($sub, $st) until False $font_tree[ubound($font_tree)-1][1] = $sub wend return $font_tree endfunc ; -------------------------------------------------------------------------- func EnumFontStyles($font_tree, $family) local $styles[0] $idx = _ArrayBinarySearch($font_tree, $family) if ($idx >= 0) then ; Get base family styles $a = _WinAPI_EnumFontFamilies(0, $family, $ANSI_CHARSET, -1) for $i = 1 to $a[0][0] _ArrayAdd($styles, $a[$i][2]) next ; Get subfamily styles $sub = $font_tree[$idx][1] for $i in $sub _ArrayAdd($styles, $i) next endif _ArraySort($styles) return _ArrayUnique($styles, Default, Default, Default, $ARRAYUNIQUE_NOCOUNT) endfunc /John
  14. FWIW, I just ended up grouping font styles based on their names (e.g., all styles that begin 'Bahnschrift' group under the family Bahnschrift, and so on). It more or less works passably. It doesn't produce the same groupings (quite) as _ChooseFont(), since I was never able to determine how _ChooseFont() determines those groupings. I even posted to stackoverflow to see if any Windows internals guru might have some insight. But so far, no takers. /John
  15. I might have spoken too soon. (Which isn't to say that you don't still rock ...) fms_metadata.xml doesn't appear to be a complete list. There are quite a few fonts that enumerate with _WinAPI_EnumFontFamilies("") that aren't in the file. Bahnschrift, for instance, isn't there (at least not on my system). 😐 /John
  16. Wow! Dude, you rock. I actually had a bash window open in that directory, nosing around the files. (Windows Explorer won't show you anything but fonts in that directory). But I somehow missed that one. Will take a look and see how far I get ... /John
  17. I'm glad it isn't just me. Agreed, that is more intuitive. The question is, how does it "pull all the Styles together"? How does it know that they go together? I'm hardly an expert on fonts. I've just spent some time staring at the MS documentation for EnumFontFamiliesEx() and looking at the structure of the .ttf files in the Windows Fonts directory. From what I can see, there isn't anything that ties "Calibri" and "Calibri Light" together except that they both begin with the string "Calibri". Likewise "Bahnschrift", "Banschrift Condensed", "Banschrift Light", and so on -- they all start with the string "Bahnschrift". I could imagine writing code to group the Styles together based on their common name stem. But a quick perusal of some of the other font names suggests that won't be correct. For example, there's Segoe UI, Segoe UI Emoji, Segoe UI Historic, and Segoe UI Symbol. They all share the common stem "Segoe UI". But the do not evidently belong together. Both _ChooseFont() and the Windows Font Settings agree on this, and list them separately. Same with Cambria and Cambria Math. There is obviously some logic by which you can decide when to pull Styles together and display them as one and when not to, which ChooseFont and the Windows Font Settings evidently share. In my probably too limited understanding, I have been unable to find what it is. The practical upshot is that if I were to implement a choose-font GUI based on _WinAPI_EnumFontFamilies(), lacking any clear method for grouping entries together, I'd end up displaying twelve variants of Bahnschrift in the primary Font Family window. Which doesn't seem very rewarding. 😕 (BTW, I realize this is probably more of a Windows API issue than an AutoIt issue, since as best as I can tell, _WinAPI_EnumFontFamilies() just passes straight through to the gdi32.dll EnumFontFamiliesExW() function. I was just hoping someone might have wrestled with this before and have some insight I clearly lack ...)
  18. My confusion grows. On my system, there is a single Bahnschrift .ttf file (bahnschrift.ttf). It evidently contains 15 styles (Sub Families? Font Faces?). As usual, Windows Settings/Explorer and _ChooseFont() display them the way I'd expect -- a single Font entry with 15 different variants (_ChooseFont() calls them Styles; Windows Settings calls them font faces). Here it makes sense to me how Windows and _ChooseFont() knows they are grouped together -- they're all in the same TrueType file. Calling _WinAPI_EnumFontFamilies("") does not return them all as one family. It mostly breaks them out into separate families. It returns 12 separate families in all (Bahnschrift, Bahnschrift Condensed, Bahnschrift Light, Bahnschrift SemiBold, ...). So here, even though I think _WinAPI_EnumFontFamilies() should understand that these are grouped together, it still doesn't. There is obviously something here I just fail to understand.
  19. I think that sums up my confusion. If that's so, my expectation would be that if I call _WinAPI_EnumFontFamilies(""), it would only return one family ("DejaVu Serif"), instead of two ("DejaVu Serif" and "DejaVu Serif Condensed"). And then if I call _WinAPI_EnumFontFamilies("DejaVu Serif"), I'd get the Condensed styles too. Instead, it seems the function regards the Condensed styles as a separate family. It's not a huge deal, really. It just means if I were to create a font selection GUI using this methodology, it would display two separate families instead of combining them together like Windows and _ChooseFont() do. By way of example with a more standard font, the same thing happens on my system with Calibri. There are 6 Calibri *.ttf files in the C:\Windows\Fonts directory, corresponding to Regular, Italic, Bold, Bold Italic, Light and Light Italic. Windows font viewers (Settings, and navigating to the C:\Windows\Fonts folder in Windows Explorer) correctly group all 6 under the family "Calibri". But _WinAPI_EnumFontFamilies() returns Calibri and Calibri Light as separate families. Try though I might, I can't figure out how Windows (and _ChooseFont()) are programmatically determining that these all belong together. There isn't anything in the .ttf files, nor the C:\Windows\Fonts directory, nor the registry that I can find that associates them. Again, not really that big a deal. It's more in the "Why can't I figure this out? There must be a way ..." category. /John EDIT: In fact, if I use a font viewer app (https://us.fontviewer.de) to examine the .ttf files, it displays "Calibri" as the Family for the first four files, and "Calibri Light" as the Family for the light files. It seems these are different families. Yet Windows and _ChooseFont() know to group them together somehow. I suppose it could simply be going by their similar names, but that seems not reliable.
  20. I had seen the article you mentioned. And what you say makes sense. But unless I'm being especially dense (a distinct possibility), it still doesn't make clear to me: If DejaVu Serif and DejaVu Serif Condensed are in different families, by what criteria does ChooseFont determine that they should be grouped together under the single heading "DejaVu Serif"? The Windows Fonts Settings page does the same.
  21. Yes. Shortly after I posted, I did that. So then I guess my question is: Why (and how) does that Win32 API function decide that all 8 DejaVu Serif styles belong together, but _WinAPI_EnumFontFamilies() doesn't. But I guess maybe that's more of a Windows question than an AutoIt question ... /John
  22. In short, I'm trying to replicate some of the functionality of _ChooseFont(). A quick Google search suggests I'm not the first person to consider this, and at least one of the answers is to use _WinAPI_EnumFontFamilies(). Which seems reasonable. I don't quite get one thing about it, though. For example, I have a font installed on my system named DejaVu Serif. There are actually 8 associated font faces: DejaVu Serif DejaVu Serif Bold DejaVu Serif Bold Italic DejaVu Serif Italic DejaVu Serif Condensed DejaVu Serif Condensed Bold DejaVu Serif Condensed Bold Italic DejaVu Serif Condensed Italic Inspection of the C:\Windows\Fonts directory shows these are TrueType fonts, kept in 8 separate *.ttf files. However, when I view them through Windows Explorer, it is clever enough to combine them into 8 variants of the same font, called DejaVu Serif. Similarly, if I call _ChooseFont(), it displays DejaVu Serif only once in the Font list, with each of the 8 different font faces as a separate entry in the Font Style list. On the other hand, if I call _WinAPI_EnumFontFamilies() with a null string as the second argument, it lists DejaVu Serif and DejaVu Serif Condensed as separate entries in the return array. If I call _WinAPI_EnumFontFamilies(0, "DejaVu Serif", ...) it returns four items (the first four in the list above). If I call _WinAPI_EnumFontFamilies(0, "DejaVu Serif Condensed", ...) I get the second four. As (I think) I understand it, you should call _WinAPI_EnumFontFamilies() once with an empty string for the typeface name, and get one font in each available typeface. Then you call it a second time with the specific typeface name to get all the fonts within the specified name. Following that paradigm, I'd always get these fonts in two separate groups, which is not how they appear in either Windows Explorer or _ChooseFont(). I assume _ChooseFont() is using _WinAPI_EnumFontFamilies() (or more likely, I suppose, the corresponding underlying Windows function). How does it know that these 8 fonts "go together"? Simply by their similar names? Appreciate any insight anyone might have. Thanks! /John
  23. Yes, that makes sense. Even though I knew GUICtrlCreateListView() returns a Control ID and the UDF function returns a window handle, I would have sworn there were instances where I ran GUICtrl* functions on the return from the UDF function and it worked anyway. At some point, even though I didn't understand it, I formed the impression that the functions in question just took care of it for you. But I can't find any such instances in my code now. So either I replaced them, or I dreamed it. In any event, there doesn't seem to be any UDF function to change the font of a UDF-created ListView. So I guess using _WinAPI_SetFont() is my only option. It seems to work, so I'm not knocking it. /John
  24. FWIW, I haven't been able to get GUICtrlSetFont() to work when the ListView is created with _GUICtrlListView_Create(). It only seems to work when the ListView is created with GUICtrlCreateListView(). I tried passing the return value from _GUICtrlListView_Create() directly to GUICtrlSetFont(), and that didn't work. I think _GUICtrlListView_Create() returns a handle, not a control ID. So I tried getting the control ID from the handle with _WinAPI_GetDlgCtrlID() and passing that to GUICtrlSetFont(). That didn't seem to work either. I ended up using WinAPI_SetFont() to set the font for the ListView I created with _GUICtrlListView_Create(). /John
  25. Hi again Melba. Hope I found the right place. 😁 Thanks again for the quick drag-drop/WM_NOTIFY fix. No problems with that so far. So what I'm basically doing is this: I had an existing pretty well filled-out script that used ListView's, and decided I wanted to switch over to ListViewEx. In light of the warning about 'script-breaking changes', rather than start to overhaul my existing script, I created a small test script (which you have seen) which mimics the behavior of the larger script. I'm going through and identifying all the ListView functions I'm using, and making sure they still seem to work with ListViewEx (in a smaller, more manageable and isolated environment). All seems to be well. Basically, everything I had been doing I seem to also be able to do with ListViewEx. There are a couple things, though -- they seem to work properly, but I'm wondering if they aren't questionable behavior: Any reason I can't add and delete items using the standard functions [_GUICtrlListView_AddItem(), _GUICtrlListView_DeleteItem()] after I create the ListView with _GUICtrlListView_Create(), as long as I do it before I call _GUIListViewEx_ReadToArray() and _GUIListViewEx_Init()? I have $LVS_EX_FULLROWSELECT set in my ListView, and I'm not doing any individual cell selection or editing. Will _GUICtrlListView_GetSelectedIndices() still work to determine the index of the currently selected row? I also in some instances want to programmatically set which row is selected, so I use _GUICtrlListView_SetItemSelected(). Is that risky? As I say, these things do seem to work. But I'd be concerned if you thought they shouldn't ... Thanks again! (And BTW, lest I forget to ever say so -- this UDF is pretty amazing.) /John
×
×
  • Create New...