September 29, 2004 From: Bob Zale, President PowerBASIC, Inc. PowerBASIC Gazette #42 - What about those Windows Controls? =========================================================== Windows Controls. An essential part of Windows GUI programming. But do any of us really know all there is to know about them? Even the standard controls like Buttons and TextBoxes? Of course not! So here's the next in a series of overviews... whether you're a novice or pro, it's likely worth it to review all you can find! But first, would you indulge me? Would you help us spread the word about PowerBASIC? You know, you're the world's best PowerBASIC advertisement. And every time we add a PowerBASIC customer, it helps us all. Every new user is an investment in the future... with more users, we'll create better products, deliver them sooner, and keep the pricing right for you. How about it? Will you tell a friend about PowerBASIC? I hope so. We'll make it easy for you to "Share the Power"! {smile} Anyway, here's the plan... You give us a name (or a few names), and we'll send just one short, informative e-mail under your name and ours. We won't follow up. We'll never use their e-mail again, unless ask us directly to do so. So, Share the Power! Just GoTo... http://www.powerbasic.com/bin/ps.exe You'll see the text of the message and add a contact name! The message is harmless, yet informative. And just think of the compilers we could build for you if everyone brought us just one new PowerBASIC user! ListBox - Tips and Tricks by Borje Hagsten ===================================================================== Windows provides four controls to present a list of items or choices for selection by the user: the standard ListBox, the standard ComboBox and the more advanced ListView and Treeview. Here, we'll concern ourselves with just the ListBox. The standard ListBox is a very powerful control, offering a large range of choices. In the older Win95/98/ME systems, you were limited to 32,736 items per ListBox. However, with WinNT-based systems, the capacity has been greatly expanded to 32-bit long integer range. Creation, available styles, notification messages, and the like, are already well covered in PowerBASIC Help (PBWin.hlp - see CONTROL ADD LISTBOX), and in Win32.hlp as well. Don't forget to review those items carefully for some really great ideas and documentation. Also, there are many useful wrapper functions (like Listbox_SetCurSel) to be found in the file Commctrl.inc on your PowerBASIC disk. Since a lot of information is readily available, we'll try to focus on some things which are just not covered there. ===================================================================== Replacing a ListBox item's text ------------------------------- Of all the commands available for the ListBox, there is no single command to replace the text of an existing item. The following procedure is created for easy use in DDT dialogs. The first parameter is the handle of the dialog, while the second parameter is the id of the ListBox control. The third parameter is the zero-based item number to replace (IOW, the first item is 0), and the fourth parameter is the replacement text. '===================================================================== FUNCTION Listbox_Replace (BYVAL hDlg AS DWORD, BYVAL CtrlId AS LONG, _ BYVAL Index AS DWORD, BYVAL txt AS STRING) _ AS LONG '-------------------------------------------------------------------- ' Replace a ListBox item's text ' Example call from inside a dialog CallBack procedure: ' lRes = Listbox_Replace (CBHNDL, %IDC_LISTBOX1, itemNum, "New text") '------------------------------------------------------------------ LOCAL lRes AS LONG CONTROL SEND hDlg, CtrlId, %LB_DELETESTRING, Index, 0 TO lRes IF lRes = %LB_ERR THEN ' if index was out of range FUNCTION = %LB_ERR ' return %LB_ERR to indicate error EXIT FUNCTION ' and exit function END IF CONTROL SEND hDlg, CtrlId, %LB_INSERTSTRING, Index, STRPTR(txt) TO lRes FUNCTION = lRes ' return the result from %LB_INSERTSTRING END FUNCTION '-------------------------------------------------------------------- ===================================================================== Adding many items to a ListBox ------------------------------- It's usually best to limit the number of items in a ListBox to some reasonable number -- we don't want to overwhelm the user! However, there are always some exceptions. For example, if the items are properly sorted prior to display, the user won't be forced to read every single entry in order to make his choice. Unfortunately, adding many items to a standard ListBox can take a bit of time. That said, a trick to speed things up is pre-allocation of memory for them, using the %LB_INITSTORAGE message. Microsoft Help says this only applies to Win95/98/ME systems, but my tests in WinXP show it works fine on NT systems as well. This trick can increase the overall execution speed a lot. The following procedure demonstrates how to quickly add all the items from a string array to a ListBox. Even if all the items aren't saved in a single array, you can still enhance performance by estimating how many will be added, and how much memory they'll need. A call to %LB_INITSTORAGE with the estimates will still be a big time-saver. You can adjust the code to your own needs. See also Win32api.hlp or MSDN for more info on %LB_INITSTORAGE. '===================================================================== FUNCTION Listbox_AddArray (BYVAL hDlg AS DWORD, BYVAL CtrlId AS LONG, _ MyArray() AS STRING) AS LONG '-------------------------------------------------------------------- ' Fill a ListBox with array items ' Pre-allocates memory for increased speed and returns total item count ' Example call: cnt = Listbox_AddArray(CBHNDL, %IDC_LISTBOX1, sArray()) '---------------------------------------------------------------------- LOCAL c AS LONG, ln AS LONG FOR c = LBOUND(MyArray) TO UBOUND(MyArray) ' calculate memory needs ln = ln + LEN(MyArray(c)) + 1 ' +1/each for trailing $NUL NEXT c = UBOUND(MyArray) - LBOUND(MyArray) + 1 ' total number of items CONTROL SEND hDlg, %IDC_LISTBOX1, %LB_INITSTORAGE, c, ln ' allocate memory FOR c = LBOUND(MyArray) TO UBOUND(MyArray) ' add the items to the LixtBox CONTROL SEND hDlg, CtrlId, %LB_ADDSTRING, 0, STRPTR(MyArray(c)) NEXT CONTROL SEND hDlg, CtrlId, %LB_GETCOUNT, 0, 0 TO c ' get/return item count FUNCTION = c END FUNCTION '-------------------------------------------------------------------- ===================================================================== OwnerDrawn ListBox ------------------------------- Microsoft provides a way to handle drawing of all ListBox items with your own code. This gives us the possibility to do wonderful stunts, like creating a list with images, using different fonts and colors, drawing grid lines around items, and much more. An example of this can be found in your PBWin70\Samples\DDT\BmpList\... folder, which shows how to use an ownerdrawn list to present images. Since this article already has brought up the subject of adding many items to a ListBox, maybe it can be interesting to take a look at how to use a standard ListBox as a virtual list. A virtual list holds no items - instead we use a global array and tell the ListBox how many items it contains. The ListBox just sets up empty space and the vertical scrollbar for the items. The advantage of this method is that the ListBox doesn't have to allocate memory and you get an instant view, no matter how large the list! Of course, there are some system limits for Win95/98/ME, as explained earlier. The following DDT example shows how a standard ListBox can display a global array. When the array is filled, %LB_SETCOUNT is called to tell the ListBox the item count. All visible items are drawn one by one, under %WM_DRAWITEM, where you can manipulate the appearance in many ways. For example, in the DrawText call below, you might change %DT_LEFT to %DT_CENTER for centered items, or to %DT_RIGHT for right-alignedment. See also Win32api.hlp or MSDN for more info on DrawText and other appropriate API calls. '==================================================================== ' OwnerDrawn Virtual ListBox, DDT example '-------------------------------------------------------------------- #COMPILE EXE #INCLUDE "WIN32API.INC" '--------------------------------- %IDC_LISTBOX1 = 101 '--------------------------------- GLOBAL sArray() AS STRING '-------------------------------------------------------------------- ' Program entrance '-------------------------------------------------------------------- FUNCTION PBMAIN LOCAL hDlg AS DWORD DIALOG NEW 0, "Virtual ListBox", , , 120, 150, _ %WS_CAPTION OR %WS_SYSMENU TO hDlg CONTROL ADD LISTBOX, hDlg, %IDC_LISTBOX1, , 5, 5, 110, 124, _ %WS_CHILD OR %WS_TABSTOP OR %WS_VSCROLL OR _ %LBS_OWNERDRAWFIXED OR %LBS_NODATA, _ %WS_EX_CLIENTEDGE CONTROL ADD BUTTON, hDlg, %IDCANCEL, "&Close", 64, 131, 50, 14 DIALOG SHOW MODAL hDlg, CALL DlgProc END FUNCTION '-------------------------------------------------------------------- ' Main dialog's callback procedure '-------------------------------------------------------------------- CALLBACK FUNCTION DlgProc LOCAL c AS LONG, lpDis AS DRAWITEMSTRUCT PTR SELECT CASE CBMSG CASE %WM_INITDIALOG '--------------------------------------------------------- ' Dim the global array and set some text to its items, ' then tell the ListBox how many items the array contains. '--------------------------------------------------------- REDIM sArray(32000) FOR c = 0 TO UBOUND(sArray) sArray(c) = "This is item" + STR$(c) NEXT CONTROL SEND CBHNDL, %IDC_LISTBOX1, _ %LB_SETCOUNT, UBOUND(sArray) + 1, 0 '--------------------------------------------------------- CASE %WM_COMMAND SELECT CASE CBCTL CASE %IDCANCEL IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN DIALOG END CBHNDL END IF CASE %IDC_LISTBOX1 IF CBCTLMSG = %LBN_SELCHANGE THEN ' On double-click, get current selection CONTROL SEND CBHNDL, %IDC_LISTBOX1, _ %LB_GETCURSEL, 0, 0 TO c ' and show related text in dialog's caption DIALOG SET TEXT CBHNDL, sArray(c) ELSEIF CBCTLMSG = %LBN_DBLCLK THEN ' do whatever on double-click.. END IF END SELECT CASE %WM_DRAWITEM IF CBWPARAM <> %IDC_LISTBOX1 THEN EXIT FUNCTION 'ensure it's our list lpdis = CBLPARAM IF @lpdis.itemID = &HFFFFFFFF THEN EXIT FUNCTION ' empty list SELECT CASE @lpdis.itemAction CASE %ODA_DRAWENTIRE, %ODA_SELECT ' DRAW THE BACKGROUND AND SET COLORS TO USE IF (@lpdis.itemState AND %ODS_SELECTED) = 0 THEN 'un-selected FillRect @lpdis.hDC, @lpdis.rcItem, _ GetSysColorBrush(%COLOR_WINDOW) SetBkColor @lpdis.hDC, GetSysColor(%COLOR_WINDOW) SetTextColor @lpdis.hDC, GetSysColor(%COLOR_WINDOWTEXT) ELSE ' selected item FillRect @lpdis.hDC, @lpdis.rcItem, _ GetSysColorBrush(%COLOR_HIGHLIGHT) SetBkColor @lpdis.hDC, GetSysColor(%COLOR_HIGHLIGHT) SetTextColor @lpdis.hDC, GetSysColor(%COLOR_HIGHLIGHTTEXT) END IF ' DRAW THE TEXT ' hDC is the device context to draw in ' itemID is current item's number ' rcItem is current item's coordinates ' By decreasing its width, we get a nice text margin InflateRect @lpdis.rcItem, -3, 0 DrawText @lpdis.hDC, _ BYVAL STRPTR(sArray(@lpdis.itemID)), _ LEN(sArray(@lpdis.itemID)), _ @lpdis.rcItem, _ %DT_LEFT OR %DT_SINGLELINE OR %DT_VCENTER FUNCTION = %TRUE 'DRAW FOCUS RECT, IF IN FOCUS.. CASE %ODA_FOCUS CALL DrawFocusRect(@lpdis.hDC, @lpdis.rcItem) FUNCTION = %TRUE END SELECT END SELECT END FUNCTION '-------------------------------------------------------------------- ======================================================================= ======================================================================= If you haven't yet acquired all three PowerBASIC Compilers, now might be a good time to look a bit further. Pricing remains at the most competitive levels known in our industry. PB/CC is our Console Compiler -- with a text mode interface to 32-bit Windows. PB 7 for Windows is oriented towards a GUI (graphical user interface) for a typical Windows "look and feel". With all of the new extensions, you won't believe how easy it is to build real GUI applications! PB/Forms is our new, state-of-the-art visual designer. It works with PowerBASIC 7 to build GUIs almost as fast as you can imagine them. PowerTree BTree Manager 1.1 is the latest release of this time-tested product. If you like "Faster/Smaller", then PowerTree is for you. PowerTree offers a concise, proprietary B+Tree algorithm for indexed data management. You design data files any way you want. PowerTree uses them at lightning speed. Access your list in zip code sequence, alphabetically, or use any other class. You'll find a record for "Clint Eastwood", out of thousands, in a heartbeat. In fact, find a record which just sounds like "Eastwood", but spelled differently, just as easily. PowerTree is friendly. Just 14 functions to learn, not hundreds. And with auto-locking, multi-user/multi-threading is a breeze. PowerTREE supports Win32, DOS, even Win16, in one version. It's priced at just $99, aAnd there's never a royalty for distribution with your code. Buy it once, use and distribute forever. More information? Sure, it's very simple. Just click to go to each or all of the PowerBASIC product pages... PB/CC 3.0: http://www.powerbasic.com/products/pbcc/ PB/WINDOWS 7.0: http://www.powerbasic.com/products/pbdll32/ PowerBASIC Forms1.5: http://www.powerbasic.com/products/pbforms/ PowerTREE: http://www.powerbasic.com/products/powertree/ Graphics Tools: http://www.powerbasic.com/products/graftool/ SQL Tools: http://www.powerbasic.com/products/sqltools/ Console Tools: http://www.powerbasic.com/products/contools/ PB/WIN 7.0 is attractively priced at $199.00, while PB/CC 3.0 is just $169.00. Upgrades from the prior versions are just $99 and $89. PowerBASIC Forms is priced at $99, and upgrades from 1.0 are just $39. Graphics Tools Standard and Pro are $69.95 and $139.95. You can order with ease by just replying to this e-mail. You can call us at (800)780-7707 or (941)408-8700, fax us at (941)408-8820, place an electronic order on our web site (http://www.powerbasic.com), or even mail it in. But no matter the method you choose, please do it today and do it with confidence. Every product PowerBASIC ships for physical delivery is offered with a money-back guarantee for 30 days from the transaction date. Regards, Bob Zale, President PowerBASIC Inc. =================================================================== PowerBASIC Price List ------------------------------------------------------------------- PB/CC Console Compiler 3.0 - Full Product $169.00 PB/CC Console Compiler 3.0 - Upgrade from vs 2 89.00 PB/CC Console Compiler 3.0 - Upgrade from vs 1 119.00 Add Printed Documentation 39.00 ------------------------------------------------------------------- PowerBASIC for Windows 7.0 (GUI) - Full Product $199.00 PowerBASIC for Windows 7.0 - Upgrade from ver 6 99.00 PowerBASIC for Windows 7.0 - Upgrade from prior versions 129.00 Add Printed Documentation 39.00 PowerBASIC Forms Visual Design Tool for PB/Win 7 99.00 PowerBASIC Forms Visual Design Tool - Upgrade from 1.0 39.00 ------------------------------------------------------------------- PowerBASIC for DOS 3.5 - Full Product $99.00 PowerBASIC for DOS 3.5 - Upgrade from prior versions 49.00 Add Printed Documentation (2 book set) 29.00 ------------------------------------------------------------------- PowerTree BTree Manager for DOS and Windows $99.00 PB/Vision for DOS 20.00 PB/Xtra III for DOS and Windows 49.00 ------------------------------------------------------------------- Graphics Tools Standard ver 2 $69.95 Graphics Tools Professional ver 2 139.95 Console Tools Standard 49.95 Console Tools Professional 99.95 SQL Tools Standard Version 99.95 SQL Tools Professional Version 199.95 ------------------------------------------------------------------- Shipping/Handling costs: Software & Each Any Software 1 or 2 books Addl Book E-mail $6 N/A N/A UPS Ground/Mail US $10 $10 $6 Fedex 2-day US $16 $16 $6 Fedex 1-day US $28 $28 $6 Air Mail Canada/Mex $12 $22 $6 Air Mail Intl $16 $28 $6 Fedex Intl $34 $44 $6 ------------------------------------------------------------------- Order online at https://www.powerbasic.com/shop/ (secure server) or just send an e-mail with all pertinent information to sales@powerbasic.com and we'll take it from there! ------------------------------------------------------------------- Most PowerBASIC products (those without printed books) can now be delivered by electronic mail. No wait for a package to arrive... No high shipping costs... For just $6 per order, no matter how many products, we'll deliver directly to your computer. If you're outside the U.S., savings might be greater. You won't pay taxes or duties to a freight company or postal service because they aren't involved in the delivery. Check your tax code to be sure, but some countries charge no tax at all on transactions like this. It could just be your lucky day! ==================================================================== Is your PowerBASIC Gazette Electronic Edition subscription coming to you at home or work? If you don't want to miss a single issue, why not subscribe from both e-mail addresses? Send your subscription request to email@powerbasic.com and please include your name and all e-mail addresses you'd like to add as well as your Zip or Postal Code. If you know someone else who would enjoy this newsletter please forward a copy to them so they can subscribe. ==================================================================== All contents Copyright (c) 2004 PowerBASIC Inc All Rights Reserved. PowerBASIC is a registered trademark of PowerBASIC, Inc. PB/CC, PB/DLL, PB/Win, PowerTREE, and PowerBASIC Forms are trademarks of PowerBASIC Inc. Other names are trademarks or registered trademarks of their respective owners. ==================================================================== PowerBASIC Gazette - Electronic Edition Volume 1 - Issue 42 PowerBASIC, Inc. (800) 780-7707 Sales 1978 S. Tamiami Trail (941) 408-8700 Voice Venice, FL 34293 (941) 408-8820 Fax Visit us on the World Wide Web at http://www.powerbasic.com Email PowerBASIC Sales: sales@powerbasic.com This newsletter is only sent to e-mail addresses in our subscription list. If you have received this newsletter by mistake or no longer wish to receive it, please send a simple unsubscribe request to gazette@powerbasic.com with your name and zip/postal code. ====================================================================