Jump to content

Another (ListView) font question


DrJohn
 Share

Recommended Posts

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

Link to comment
Share on other sites

Wouldn't it be more simple to just revert to GUICtrlCreateListView?

Or  @Melba23's listview UDF?

If there isn't anything there that you can't find elsewhere, (_GUICtrlListView_Create VS GUICtrlCreateListView)

i think a good approach is to step back and look for the better path.

 

Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

> 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

Edited by DrJohn
Link to comment
Share on other sites

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

Edited by DrJohn
(Forgot to attach the script ...)
Link to comment
Share on other sites

  • Moderators

DrJohn,

I have looked inside the _GUICtrlListView_GetItemText function and the $iIndex parameter is passed directly to Windows in the following line:

_SendMessage($hWnd, $LVM_GETITEMTEXTW, $iIndex, $tItem, 0, "wparam", "struct*")

Although AutoIt is pretty good at automatically converting datatypes, Windows is not and does not like a string being passed as $wparam. Thus it works when you force the number datatype, but not when you do not.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...