[RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when Sorted=False.
Hello.
Combobox sorted property is set to False, but using API SendMessage method to fill data, items appear sorted.
Code:
Private Const CB_INITSTORAGE = &H161
Public Const CB_ADDSTRING As Long = &H143&
Declare Function SendMessage Lib "user32" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long
'Allocate memory for items to add.
Dim lngItems As Long
Dim Retval As Long
lngItems = UBound(sData)
Retval = SendMessage(Combo1.hwnd, CB_INITSTORAGE, lngItems, ByVal (lngItems * 32)) '32 bytes per item
'Add string data
For lngItems = lBound(sData) To UBound(sData)
SendMessage(Combo1.hwnd, CB_ADDSTRING, 0&, ByVal sData(lngItems))
Next lngItems
I presume that the InitStorage resets combobox style to CBS_Sort, but the VB Sorted property is read only, so can't set that at runtime.
Any idea how to prevent combox from sorting data automatically, when using SendMessage API to fill data?
Sorry, wrong alert... It seems that middle layer pulling data from table, sorts data background against sql clause sort order. Damn those junior coders.
Last edited by Tech99; Nov 18th, 2015 at 02:45 AM.
Reason: resolved...
Re: [RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when
Thanks for getting back.
Yes I've been doing a bit of testing too, it is much faster for Combos and the difference is even more pronounced when v6 Common Controls are implemented via a manifest on the exe.
Strangely I tried similar stuff on a ListBox using LB_INITSTORAGE and LB_ADDSTRING messages but no real differences there, indeed List.AddItem may be a tad faster and a v6 Common Controls manifest makes little difference.
Re: [RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when
You might gain better performance if listbox.Visible = False during initial load. The combobox has no visible GUI during load to update, no scrollbars. LockWindowUpdate may also be useful for the listbox? Just some thoughts
Insomnia is just a byproduct of, "It can't be done"
Re: [RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when
>You might gain better performance if listbox.Visible = False
Thanks but my tests included that old trick. Using either method I'm finding filling ListBoxes is faster than filling Combos.
Re: [RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when
Just some notes from MSDN
CB_ADDString
Comclt32.dll version 5.0 or later: If CBS_LOWERCASE or CBS_UPPERCASE is set, the Unicode version of CB_ADDSTRING alters the string. If using read-only global memory, this causes the application to fail.
LB_ADDString
For an ANSI application, the system converts the text in a list box to Unicode using CP_ACP. This can cause problems. For example, accented Roman characters in a non-Unicode list box in Japanese Windows will come out garbled. To fix this, either compile the application as Unicode or use an owner-drawn list box.
Insomnia is just a byproduct of, "It can't be done"
Re: [RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when
Another observation re Combos. API method seems to have little or no advantage over AddItem when Combo.Style = 1 - SimpleCombo. In this case when v6 manifest is applied API method appears slightly slower.
Some people will recommend using LockWindowUpdate, but this is wrong. LockWindowUpdate disables drawing in the window you specify, but suppressing flickering during updates is not what it was designed for.
One clear limitation limitation of LockWindowUpdate is that only one window can be locked for update at a time. So if two windows each try the LockWindowUpdate trick at the same time, only one of them will succeed. That's not particularly reliable, now, is it.
The purpose of LockWindowUpdate is to assist code that is drawing drag/drop feedback. If you are drawing the cursor for a drag/drop operation, you don't want the window beneath the cursor to start drawing (and thereby overwrite your beautiful cursor). So you lock the window while you draw the cursor and unlock it when the cursor leaves the window.
Re: [RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when
Someone writing a MSDN blog, tells that using LockWindowUpdate is wrong method to speed up filling LB or CB, it's designed for different usage.
In this case, the blog comments don't really apply completely do they? You're loading the listbox in a tight loop, nothing else in your app will be updating or even working until the loop finishes. Didn't click on your link, but if someone is horrified with usage of LockWindowUpdate, maybe SendMesssage:WM_SETREDRAW might be more apt for the job?
When I replied, I only offered it as an option because that option has been used for decades, right or wrong, in the opinion of whoever. Granted, that API wasn't designed for that purpose, but has that ever stopped someone from using something that may work for them?
Insomnia is just a byproduct of, "It can't be done"
Re: [RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when
Possibly, but blogger recommends to disable refreshing using SetWindowRedraw API.
First, you can disable redraw while you add the items. (This tip works for all controls, actually.)
SetWindowRedraw(hwnd, FALSE);
... add the items ...
SetWindowRedraw(hwnd, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
Re: [RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when
In case anyone else was confused and tried to find MSDN documentation for SetWindowRedraw:
SetWindowRedraw() is a macro from <windowsx.h>. It is a convenient way of sending the WM_SETREDRAW message.
Just FYI for anyone asking, "What the heck is SetWindowRedraw?"
Insomnia is just a byproduct of, "It can't be done"
Re: [RESOLVED] Combobox CB_ADDSTRING with SendMessage API - appears sorted, even when
Originally Posted by LaVolpe
In this case, the blog comments don't really apply completely do they? You're loading the listbox in a tight loop, nothing else in your app will be updating or even working until the loop finishes.
It is possible that a second instance of the program is also running and is trying to call the LockWindowUpdate API as well.
Originally Posted by Tech99
SendMessage Hwnd, WM_SETREDRAW, True, ByVal 0&
The proper value should actually be 1& and not -1% (C/C++'s TRUE BOOL value vs VB's True Boolean value), but it doesn't really matter I guess since Windows likely just treats all non-zero values as TRUE, just as VB does. Nevertheless, I still prefer to pass the correct values whenever possible.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0