CWindow RC10

Started by José Roca, June 10, 2016, 04:20:13 PM

Previous topic - Next topic

José Roca

Includes AfxCtl.inc, with wrappers for the Windows Common Controls messages that have no macros in windowsx.bi or commonctrl.bi, and some more. The only missing is the Rich Edit control. Will do later.

The help file documents all the wrappers and also the macros for the common controls in windowsx and commctrl.

It has been an huge task. Hope there aren't too many mistakes.



Paul Squires

#1
Wow! Incredible! The FB version of CWindow has certainly taken shape and is extremely usable. These common wrappers are the icing on the cake.
Paul Squires
PlanetSquires Software

James Fuller

I concur. Outstanding job.

James


José Roca

An example that demonstrates the use of some of the TreeView wrappers:


' ########################################################################################
' Microsoft Windows
' File: CW_COMMCTRL_TreeView_Layout2.fbtpl
' Contents: Template - CWindow with a TreeView
' Compiler: Free Basic
' Copyright (c) 2016 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "Afx/AfxCtl.inc"
#INCLUDE ONCE "Afx/CLayout.inc"
USING Afx.CWindowClass
USING Afx.CLayoutClass

#define IDC_TREEVIEW 1001
#define IDC_EXPAND 1002
#define IDC_COLLAPSE 1003
#define IDC_TOGGLE 1004

DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                          BYVAL hPrevInstance AS HINSTANCE, _
                          BYVAL szCmdLine AS ZSTRING PTR, _
                          BYVAL nCmdShow AS LONG) AS LONG

   END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)

' ========================================================================================
' Window procedure
' ================================================================e========================
FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

   ' // Scaling ratios
   STATIC AS SINGLE rxRatio, ryRatio

   SELECT CASE uMsg

      CASE WM_CREATE
         ' // Get the scaling ratios
         rxRatio = AfxCWindowPtr(lParam)->rxRatio
         ryRatio = AfxCWindowPtr(lParam)->ryRatio
         EXIT FUNCTION

      CASE WM_COMMAND
         SELECT CASE LOWORD(wParam)
            ' // If ESC key pressed, close the application sending an WM_CLOSE message
            CASE IDCANCEL
               IF HIWORD(wParam) = BN_CLICKED THEN
                  SendMessageW hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
            ' // Collapse the root node
            CASE IDC_COLLAPSE
               DIM hTreeView AS HWND = GetDlgItem(hwnd, IDC_TREEVIEW)
               TreeView_Expand(hTreeView, TreeView_GetRoot(hTreeView), TVE_COLLAPSE)
               EXIT FUNCTION
            ' // Expand the root node
            CASE IDC_EXPAND
               DIM hTreeView AS HWND = GetDlgItem(hwnd, IDC_TREEVIEW)
               TreeView_Expand(hTreeView, TreeView_GetRoot(hTreeView), TVE_EXPAND)
               EXIT FUNCTION
            ' // Toggle the root node
            CASE IDC_TOGGLE
               DIM hTreeView AS HWND = GetDlgItem(hwnd, IDC_TREEVIEW)
               TreeView_Expand(hTreeView, TreeView_GetRoot(hTreeView), TVE_TOGGLE)
               EXIT FUNCTION
         END SELECT

      CASE WM_NOTIFY
         DIM ptnmhdr AS NMHDR PTR = CAST(NMHDR PTR, lParam)
         SELECT CASE ptnmhdr->idFrom
            CASE IDC_TREEVIEW
               IF ptnmhdr->code = NM_DBLCLK THEN
                  ' // Retrieve the handle of the TreeView
                  DIM hTreeView AS HWND = GetDlgItem(hwnd, IDC_TREEVIEW)
                  ' // Retrieve the selected item
                  DIM hItem AS HTREEITEM = TreeView_GetSelection(hTreeView)
                  ' // Retrieve the text of the selected item
                  DIM wszText AS WSTRING * 260
                  TreeView_GetItemText(hTreeView, hItem, @wszText, 260)
                  MessageBox hwnd, wszText, "", MB_OK
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_GETMINMAXINFO
         ' // Set the pointer to the address of the MINMAXINFO structure
         DIM ptmmi AS MINMAXINFO PTR = CAST(MINMAXINFO PTR, lParam)
         ' // Set the minimum and maximum sizes that can be produced by dragging the borders of the window
         ptmmi->ptMinTrackSize.x = 350 * rxRatio
         ptmmi->ptMinTrackSize.y = 150 * ryRatio
         EXIT FUNCTION

      CASE WM_SIZE
         ' // Adjusts the controls
         DIM pLayout AS CLayout PTR = CAST(CLayout PTR, GetPropW(hwnd, "CLAYOUTPTR"))
         IF pLayout THEN pLayout->AdjustControls
         EXIT FUNCTION

    CASE WM_DESTROY
         ' // Remove the property
         RemovePropW hwnd, "CLAYOUTPTR"
          ' // End the application
         PostQuitMessage(0)
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to DefWindowProc
   FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                  BYVAL hPrevInstance AS HINSTANCE, _
                  BYVAL szCmdLine AS ZSTRING PTR, _
                  BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   AfxSetProcessDPIAware

   DIM pWindow AS CWindow
   pWindow.Create(NULL, "CWindow with a TreeView", @WndProc)
   pWindow.ClassStyle = CS_DBLCLKS   ' // Change the window style to avoid flicker
   pWindow.SetClientSize(337, 370)
   pWindow.Center

   ' // Add a TreeView
   DIM hTreeView AS HWND
   hTreeView = pWindow.AddControl("TreeView", , IDC_TREEVIEW, "")
   pWindow.SetWindowPos hTreeView, NULL, 8, 8, 320, 320, SWP_NOZORDER

   ' // Add items to the TreeView
   DIM AS HTREEITEM hRoot, hNode, hItem
   ' // Create the root node
   hRoot = TreeView_AddRootItem(hTreeView, "Root")
   ' // Create a node
   hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 1")
   ' // Insert items in the node
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 1")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 2")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 3")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 4")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 5")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 6")
   ' // Expand the node
   TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
   ' // Create another node
   hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 2")
   ' // Insert items in the node
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 1")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 2")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 3")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 4")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 5")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 6")
   ' // Expand the node
   TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
   ' // Create another node
   hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 3")
   ' // Insert items in the node
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 1")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 2")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 3")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 4")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 5")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 6")
   ' // Expand the node
   TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
   ' // Create another node
   hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 4")
   ' // Insert items in the node
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 1")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 2")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 3")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 4")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 5")
   hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 6")
   ' // Expand the node
   TreeView_Expand(hTreeView, hNode, TVM_EXPAND)

   ' // Expand the root node
   TreeView_Expand(hTreeView, hRoot, TVE_EXPAND)

   pWindow.AddControl("Button", , IDC_EXPAND, "&Expand", 8, 338, 75, 23)
   pWindow.AddControl("Button", , IDC_COLLAPSE, "&Collapse", 90, 338, 75, 23)
   pWindow.AddControl("Button", , IDC_TOGGLE, "&Toggle", 172, 338, 75, 23)

   ' // Add a cancel button
   pWindow.AddControl("Button", , IDCANCEL, "&Cancel", 254, 338, 75, 23)

   ' // Anchor the controls
   DIM pLayout AS CLayout = pWindow.hWindow
   SetPropW pWindow.hWindow, "CLAYOUTPTR", @pLayout
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_TREEVIEW), AFX_ANCHOR_HEIGHT_WIDTH)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_EXPAND), AFX_ANCHOR_BOTTOM)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_COLLAPSE), AFX_ANCHOR_BOTTOM)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_TOGGLE), AFX_ANCHOR_BOTTOM)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDCANCEL), AFX_ANCHOR_BOTTOM_RIGHT)

   

   ' // Process Windows messages
   FUNCTION = pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================


José Roca

#4
As some like to create the controls in WM_CREATE (à la Petzold), there are two ways to do it with CWindow. In the following example, we get a pointer to the CWindow class calling AfxCWindowPtr(lParam) and using hwnd as the parent instead of pWindow.hWindow or omiting that parameter because CWindow does not know the window handle until WM_CREATE has exited.


' ########################################################################################
' Microsoft Windows
' File: CW_COMMCTRL_TreeView_Layout2.fbtpl
' Contents: Template - CWindow with a TreeView
' Compiler: Free Basic
' Copyright (c) 2016 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "Afx/AfxCtl.inc"
#INCLUDE ONCE "Afx/CLayout.inc"
USING Afx.CWindowClass
USING Afx.CLayoutClass

#define IDC_TREEVIEW 1001
#define IDC_EXPAND 1002
#define IDC_COLLAPSE 1003
#define IDC_TOGGLE 1004

DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                          BYVAL hPrevInstance AS HINSTANCE, _
                          BYVAL szCmdLine AS ZSTRING PTR, _
                          BYVAL nCmdShow AS LONG) AS LONG

   END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)

' ========================================================================================
' Window procedure
' ================================================================e========================
FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

   STATIC AS SINGLE rxRatio, ryRatio
   STATIC hTreeView AS HWND

   SELECT CASE uMsg

      CASE WM_CREATE
         ' Get a pointer to the CWindow clas
         DIM pWindow AS CWindow PTR = AfxCWindowPtr(lParam)
         ' // Get the scaling ratios
         rxRatio = pWindow->rxRatio
         ryRatio = pWindow->ryRatio
         ' // Add a TreeView
         ' // Note that we have are using hwnd as the parent instead of pWindow.hWindow
         ' // because the CWindow class does not know the handle of the window until
         ' // WM_CREATE message has exited.
         hTreeView = pWindow->AddControl("TreeView", hwnd, IDC_TREEVIEW, "")
         pWindow->SetWindowPos hTreeView, NULL, 8, 8, 320, 320, SWP_NOZORDER
         ' // Add items to the TreeView
         DIM AS HTREEITEM hRoot, hNode, hItem
         ' // Create the root node
         hRoot = TreeView_AddRootItem(hTreeView, "Root")
         ' // Create a node
         hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 1")
         ' // Insert items in the node
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 1")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 2")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 3")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 4")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 5")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 6")
         ' // Expand the node
         TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
         ' // Create another node
         hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 2")
         ' // Insert items in the node
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 1")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 2")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 3")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 4")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 5")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 6")
         ' // Expand the node
         TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
         ' // Create another node
         hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 3")
         ' // Insert items in the node
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 1")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 2")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 3")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 4")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 5")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 6")
         ' // Expand the node
         TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
         ' // Create another node
         hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 4")
         ' // Insert items in the node
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 1")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 2")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 3")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 4")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 5")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 6")
         ' // Expand the node
         TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
         ' // Expand the root node
         TreeView_Expand(hTreeView, hRoot, TVE_EXPAND)
         ' // Add the buttons
         pWindow->AddControl("Button", hwnd, IDC_EXPAND, "&Expand", 8, 338, 75, 23)
         pWindow->AddControl("Button", hwnd, IDC_COLLAPSE, "&Collapse", 90, 338, 75, 23)
         pWindow->AddControl("Button", hwnd, IDC_TOGGLE, "&Toggle", 172, 338, 75, 23)
         pWindow->AddControl("Button", hwnd, IDCANCEL, "&Cancel", 254, 338, 75, 23)
         EXIT FUNCTION

      CASE WM_COMMAND
         SELECT CASE LOWORD(wParam)
            ' // If ESC key pressed, close the application sending an WM_CLOSE message
            CASE IDCANCEL
               IF HIWORD(wParam) = BN_CLICKED THEN
                  SendMessageW hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
            ' // Collapse the root node
            CASE IDC_COLLAPSE
               TreeView_Expand(hTreeView, TreeView_GetRoot(hTreeView), TVE_COLLAPSE)
               EXIT FUNCTION
            ' // Expand the root node
            CASE IDC_EXPAND
               TreeView_Expand(hTreeView, TreeView_GetRoot(hTreeView), TVE_EXPAND)
               EXIT FUNCTION
            ' // Toggle the root node
            CASE IDC_TOGGLE
               TreeView_Expand(hTreeView, TreeView_GetRoot(hTreeView), TVE_TOGGLE)
               EXIT FUNCTION
         END SELECT

      CASE WM_NOTIFY
         DIM ptnmhdr AS NMHDR PTR = CAST(NMHDR PTR, lParam)
         SELECT CASE ptnmhdr->idFrom
            CASE IDC_TREEVIEW
               IF ptnmhdr->code = NM_DBLCLK THEN
                  ' // Retrieve the selected item
                  DIM hItem AS HTREEITEM = TreeView_GetSelection(hTreeView)
                  ' // Retrieve the text of the selected item
                  DIM wszText AS WSTRING * 260
                  TreeView_GetItemText(hTreeView, hItem, @wszText, 260)
                  MessageBox hwnd, wszText, "", MB_OK
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_GETMINMAXINFO
         ' // Set the pointer to the address of the MINMAXINFO structure
         DIM ptmmi AS MINMAXINFO PTR = CAST(MINMAXINFO PTR, lParam)
         ' // Set the minimum and maximum sizes that can be produced by dragging the borders of the window
         ptmmi->ptMinTrackSize.x = 350 * rxRatio
         ptmmi->ptMinTrackSize.y = 150 * ryRatio
         EXIT FUNCTION

      CASE WM_SIZE
         ' // Adjusts the controls
         DIM pLayout AS CLayout PTR = CAST(CLayout PTR, GetPropW(hwnd, "CLAYOUTPTR"))
         IF pLayout THEN pLayout->AdjustControls
         EXIT FUNCTION

    CASE WM_DESTROY
         ' // Remove the property
         RemovePropW hwnd, "CLAYOUTPTR"
          ' // End the application
         PostQuitMessage(0)
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to DefWindowProc
   FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                  BYVAL hPrevInstance AS HINSTANCE, _
                  BYVAL szCmdLine AS ZSTRING PTR, _
                  BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   AfxSetProcessDPIAware

   DIM pWindow AS CWindow
   pWindow.Create(NULL, "CWindow with a TreeView", @WndProc)
   pWindow.ClassStyle = CS_DBLCLKS   ' // Change the window style to avoid flicker
   pWindow.SetClientSize(337, 370)
   pWindow.Center


   ' // Anchor the controls
   DIM pLayout AS CLayout = pWindow.hWindow
   SetPropW pWindow.hWindow, "CLAYOUTPTR", @pLayout
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_TREEVIEW), AFX_ANCHOR_HEIGHT_WIDTH)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_EXPAND), AFX_ANCHOR_BOTTOM)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_COLLAPSE), AFX_ANCHOR_BOTTOM)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_TOGGLE), AFX_ANCHOR_BOTTOM)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDCANCEL), AFX_ANCHOR_BOTTOM_RIGHT)



   ' // Process Windows messages
   FUNCTION = pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================


José Roca

The second way is to let to know CWindow the handle of the window calling pWindow->hWindow = hwnd. Adter that, we can use both hTreeView = pWindow->AddControl("TreeView", pWindow->hWIndow, IDC_TREEVIEW, "") or hTreeView = pWindow->AddControl("TreeView", , IDC_TREEVIEW, "").


' ########################################################################################
' Microsoft Windows
' File: CW_COMMCTRL_TreeView_Layout2.fbtpl
' Contents: Template - CWindow with a TreeView
' Compiler: Free Basic
' Copyright (c) 2016 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "Afx/AfxCtl.inc"
#INCLUDE ONCE "Afx/CLayout.inc"
USING Afx.CWindowClass
USING Afx.CLayoutClass

#define IDC_TREEVIEW 1001
#define IDC_EXPAND 1002
#define IDC_COLLAPSE 1003
#define IDC_TOGGLE 1004

DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                          BYVAL hPrevInstance AS HINSTANCE, _
                          BYVAL szCmdLine AS ZSTRING PTR, _
                          BYVAL nCmdShow AS LONG) AS LONG

   END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)

' ========================================================================================
' Window procedure
' ================================================================e========================
FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

   STATIC AS SINGLE rxRatio, ryRatio
   DIM hTreeView AS HWND

   SELECT CASE uMsg

      CASE WM_CREATE
         ' // Get a pointer to the CWindow clas
         DIM pWindow AS CWindow PTR
         pWindow = AfxCWindowPtr(lParam)
         ' // Get the scaling ratios
         rxRatio = pWindow->rxRatio
         ryRatio = pWindow->ryRatio
         ' // Set the window handle
         pWindow->hWindow = hwnd
         ' // Add a TreeView
         hTreeView = pWindow->AddControl("TreeView", , IDC_TREEVIEW, "")
         pWindow->SetWindowPos hTreeView, NULL, 8, 8, 320, 320, SWP_NOZORDER
         ' // Add items to the TreeView
         DIM AS HTREEITEM hRoot, hNode, hItem
         ' // Create the root node
         hRoot = TreeView_AddRootItem(hTreeView, "Root")
         ' // Create a node
         hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 1")
         ' // Insert items in the node
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 1")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 2")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 3")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 4")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 5")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 1 Item 6")
         ' // Expand the node
         TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
         ' // Create another node
         hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 2")
         ' // Insert items in the node
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 1")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 2")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 3")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 4")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 5")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 2 Item 6")
         ' // Expand the node
         TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
         ' // Create another node
         hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 3")
         ' // Insert items in the node
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 1")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 2")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 3")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 4")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 5")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 3 Item 6")
         ' // Expand the node
         TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
         ' // Create another node
         hNode = TreeView_AppendItem(hTreeView, hRoot, "Node 4")
         ' // Insert items in the node
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 1")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 2")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 3")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 4")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 5")
         hItem = TreeView_AppendItem(hTreeView, hNode, "Node 4 Item 6")
         ' // Expand the node
         TreeView_Expand(hTreeView, hNode, TVM_EXPAND)
         ' // Expand the root node
         TreeView_Expand(hTreeView, hRoot, TVE_EXPAND)
         ' // Add the buttons
         pWindow->AddControl("Button", , IDC_EXPAND, "&Expand", 8, 338, 75, 23)
         pWindow->AddControl("Button", , IDC_COLLAPSE, "&Collapse", 90, 338, 75, 23)
         pWindow->AddControl("Button", , IDC_TOGGLE, "&Toggle", 172, 338, 75, 23)
         pWindow->AddControl("Button", , IDCANCEL, "&Cancel", 254, 338, 75, 23)
         EXIT FUNCTION

      CASE WM_COMMAND
         SELECT CASE LOWORD(wParam)
            ' // If ESC key pressed, close the application sending an WM_CLOSE message
            CASE IDCANCEL
               IF HIWORD(wParam) = BN_CLICKED THEN
                  SendMessageW hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
            ' // Collapse the root node
            CASE IDC_COLLAPSE
               TreeView_Expand(hTreeView, TreeView_GetRoot(hTreeView), TVE_COLLAPSE)
               EXIT FUNCTION
            ' // Expand the root node
            CASE IDC_EXPAND
               TreeView_Expand(hTreeView, TreeView_GetRoot(hTreeView), TVE_EXPAND)
               EXIT FUNCTION
            ' // Toggle the root node
            CASE IDC_TOGGLE
               TreeView_Expand(hTreeView, TreeView_GetRoot(hTreeView), TVE_TOGGLE)
               EXIT FUNCTION
         END SELECT

      CASE WM_NOTIFY
         DIM ptnmhdr AS NMHDR PTR = CAST(NMHDR PTR, lParam)
         SELECT CASE ptnmhdr->idFrom
            CASE IDC_TREEVIEW
               IF ptnmhdr->code = NM_DBLCLK THEN
                  ' // Retrieve the selected item
                  DIM hItem AS HTREEITEM = TreeView_GetSelection(hTreeView)
                  ' // Retrieve the text of the selected item
                  DIM wszText AS WSTRING * 260
                  TreeView_GetItemText(hTreeView, hItem, @wszText, 260)
                  MessageBox hwnd, wszText, "", MB_OK
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_GETMINMAXINFO
         ' // Set the pointer to the address of the MINMAXINFO structure
         DIM ptmmi AS MINMAXINFO PTR = CAST(MINMAXINFO PTR, lParam)
         ' // Set the minimum and maximum sizes that can be produced by dragging the borders of the window
         ptmmi->ptMinTrackSize.x = 350 * rxRatio
         ptmmi->ptMinTrackSize.y = 150 * ryRatio
         EXIT FUNCTION

      CASE WM_SIZE
         ' // Adjusts the controls
         DIM pLayout AS CLayout PTR = CAST(CLayout PTR, GetPropW(hwnd, "CLAYOUTPTR"))
         IF pLayout THEN pLayout->AdjustControls
         EXIT FUNCTION

    CASE WM_DESTROY
         ' // Remove the property
         RemovePropW hwnd, "CLAYOUTPTR"
          ' // End the application
         PostQuitMessage(0)
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to DefWindowProc
   FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                  BYVAL hPrevInstance AS HINSTANCE, _
                  BYVAL szCmdLine AS ZSTRING PTR, _
                  BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   AfxSetProcessDPIAware

   DIM pWindow AS CWindow
   pWindow.Create(NULL, "CWindow with a TreeView", @WndProc)
   pWindow.ClassStyle = CS_DBLCLKS   ' // Change the window style to avoid flicker
   pWindow.SetClientSize(337, 370)
   pWindow.Center


   ' // Anchor the controls
   DIM pLayout AS CLayout = pWindow.hWindow
   SetPropW pWindow.hWindow, "CLAYOUTPTR", @pLayout
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_TREEVIEW), AFX_ANCHOR_HEIGHT_WIDTH)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_EXPAND), AFX_ANCHOR_BOTTOM)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_COLLAPSE), AFX_ANCHOR_BOTTOM)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_TOGGLE), AFX_ANCHOR_BOTTOM)
   pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDCANCEL), AFX_ANCHOR_BOTTOM_RIGHT)



   ' // Process Windows messages
   FUNCTION = pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================


José Roca

The next version of CWindow will feature the ControlHandle method, so besides GetDlgItem(pWindow.hWindow, IDC_TREEVIEW) we could also use pWindow.ControlHandle(IDC_TREEVIEW). Not a big improvement, but maybe beginners will find it easier to remember and understand than GetDlgItem.

José Roca

For one of the examples below I had the need of retrieve the path of a system dll, so I have incoporated this wrapper function to AfxWin.inc.


' ========================================================================================
' Retrieves the fully qualified path of the specified system DLL.
' ========================================================================================
PRIVATE FUNCTION AfxGetSystemDllPath (BYVAL pwszDllName AS WSTRING PTR, BYVAL pwszDllPath AS WSTRING PTR, BYVAL cchCount AS DWORD) AS LONG
   IF pwszDllName = NULL OR pwszDllPath = NULL OR cchCount = 0 THEN EXIT FUNCTION
   DIM hLib AS HMODULE
   hLib = LoadLibraryW(pwszDllName)
   IF hLib THEN
      FUNCTION = GetModuleFileNameW(hLib, pwszDllPath, cchCount)
      FreeLibrary hLib
   END IF
END FUNCTION
' ========================================================================================


José Roca

Pick Icon File Dialog

The PickIconFileDialog allows to add an icon-selection dialog box to your applications.

The following example demonstrates how to use it to display the icons from the resource file of shell32.dll. If you select an icon, the application extraxts it and sets it as the application icon.


' ########################################################################################
' Microsoft Windows
' File: CW_COMMCTRL_PickIconDlg.fbtpl
' Contents: Demonstrates the use of the Pick icon dialog.
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2016 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "win/shlobj.bi"
USING Afx.CWindowClass

CONST IDC_PICKDLG = 1001   ' // Pick icon dialog identifier

' // Forward declaration
DECLARE FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                          BYVAL hPrevInstance AS HINSTANCE, _
                          BYVAL szCmdLine AS ZSTRING PTR, _
                          BYVAL nCmdShow AS LONG) AS LONG

   END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                  BYVAL hPrevInstance AS HINSTANCE, _
                  BYVAL szCmdLine AS ZSTRING PTR, _
                  BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   AfxSetProcessDPIAware

   DIM pWindow AS CWindow
   pWindow.Create(NULL, "CWindow with a button", @WndProc)
   pWindow.SetClientSize(500, 320)
   pWindow.Center

   ' // Add buttons without position or size (it will be resized in the WM_SIZE message).
   pWindow.AddControl("Button", , IDC_PICKDLG, "&Pick")
   pWindow.AddControl("Button", , IDCANCEL, "&Close")


   ' // Process Windows messages
   FUNCTION = pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================


' ========================================================================================
' Window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

   STATIC wszIconPath AS WSTRING * MAX_PATH   ' // Path of the resource file containing the icons
   STATIC nIconIndex AS LONG                  ' // Icon index
   STATIC hIcon AS HICON                      ' // Icon handle

   SELECT CASE uMsg

      CASE WM_COMMAND
         ' // If ESC key pressed, close the application sending an WM_CLOSE message
         SELECT CASE LOWORD(wParam)
            CASE IDCANCEL
               IF HIWORD(wParam) = BN_CLICKED THEN
                  SendMessageW hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
            ' // Launch the Pick icon dialog
            CASE IDC_PICKDLG
               IF HIWORD(wParam) = BN_CLICKED THEN
                  IF LEN(wszIconPath) = 0 THEN AfxGetSystemDllPath("Shell32.dll", wszIconPath, MAX_PATH)
                  IF LEN(wszIconPath) = 0 THEN EXIT FUNCTION
                  ' // Activate the Pick Icon Common Dialog Box
                  DIM hr AS LONG = PickIconDlg(0, wszIconPath, SIZEOF(wszIconPath), @nIconIndex)
                  ' // If an icon has been selected...
                  IF hr = 1 THEN
                     ' // Destroy previously loaded icon, if any
                     IF hIcon THEN DestroyIcon(hIcon)
                     ' // Get the handle of the new selected icon
                     hIcon = ExtractIconW(GetModuleHandle(NULL), wszIconPath, nIconIndex)
                     ' // Replace the application icons
                     IF hIcon THEN
                        SendMessageW(hwnd, WM_SETICON, ICON_SMALL, cast(LPARAM, hIcon))
                        SendMessageW(hwnd, WM_SETICON, ICON_BIG, cast(LPARAM, hIcon))
                     END IF
                  END IF
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_SIZE
         IF wParam <> SIZE_MINIMIZED THEN
            ' // Resize the buttons
            DIM pWindow AS CWindow PTR = AfxCWindowPtr(hwnd)
            IF pWindow THEN pWindow->MoveWindow GetDlgItem(hwnd, IDC_PICKDLG), pWindow->ClientWidth - 230, pWindow->ClientHeight - 50, 75, 23, CTRUE
            IF pWindow THEN pWindow->MoveWindow GetDlgItem(hwnd, IDCANCEL), pWindow->ClientWidth - 120, pWindow->ClientHeight - 50, 75, 23, CTRUE
         END IF

    CASE WM_DESTROY
         ' // Destroy the icon
         IF hIcon THEN DestroyIcon(hIcon)
          ' // End the application sending a WM_QUIT message
         PostQuitMessage(0)
         EXIT FUNCTION

   END SELECT

   ' // Process Windows messages
   FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================



José Roca

#9
The following example demonstrates how to use the pick icon dialog to display the icons from our own resource file. The attached file contains the source code and the icons.


' ########################################################################################
' Microsoft Windows
' File: CW_COMMCTRL_PickIconDlg.fbtpl
' Contents: Demonstrates the use of the Pick icon dialog.
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2016 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "win/shlobj.bi"
USING Afx.CWindowClass
' $FB_RESPATH = "PickIconDialog.rc"

CONST IDC_PICKDLG = 1001   ' // Pick icon dialog identifier

' // Forward declaration
DECLARE FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                          BYVAL hPrevInstance AS HINSTANCE, _
                          BYVAL szCmdLine AS ZSTRING PTR, _
                          BYVAL nCmdShow AS LONG) AS LONG

   END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                  BYVAL hPrevInstance AS HINSTANCE, _
                  BYVAL szCmdLine AS ZSTRING PTR, _
                  BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   AfxSetProcessDPIAware

   DIM pWindow AS CWindow
   pWindow.Create(NULL, "CWindow with a button", @WndProc)
   pWindow.SetClientSize(500, 320)
   pWindow.Center

   ' // Add buttons without position or size (it will be resized in the WM_SIZE message).
   pWindow.AddControl("Button", , IDC_PICKDLG, "&Pick")
   pWindow.AddControl("Button", , IDCANCEL, "&Close")


   ' // Process Windows messages
   FUNCTION = pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================


' ========================================================================================
' Window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

   STATIC wszIconPath AS WSTRING * MAX_PATH   ' // Path of the resource file containing the icons
   STATIC nIconIndex AS LONG                  ' // Icon index
   STATIC hIcon AS HICON                      ' // Icon handle

   SELECT CASE uMsg

      CASE WM_COMMAND
         ' // If ESC key pressed, close the application sending an WM_CLOSE message
         SELECT CASE LOWORD(wParam)
            CASE IDCANCEL
               IF HIWORD(wParam) = BN_CLICKED THEN
                  SendMessageW hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
            ' // Launch the Pick icon dialog
            CASE IDC_PICKDLG
               IF HIWORD(wParam) = BN_CLICKED THEN
                  IF LEN(wszIconPath) = 0 THEN
                     ' // Get the full path of our executable
                     GetModuleFileNameW(NULL, wszIconPath, MAX_PATH)
                  END IF
                  ' // Activate the Pick Icon Common Dialog Box
                  DIM hr AS LONG = PickIconDlg(0, wszIconPath, SIZEOF(wszIconPath), @nIconIndex)
                  ' // If an icon has been selected...
                  IF hr = 1 THEN
                     ' // Destroy previously loaded icon, if any
                     IF hIcon THEN DestroyIcon(hIcon)
                     ' // Get the handle of the new selected icon
                     hIcon = ExtractIconW(GetModuleHandle(NULL), wszIconPath, nIconIndex)
                     ' // Replace the application icons
                     IF hIcon THEN
                        SendMessageW(hwnd, WM_SETICON, ICON_SMALL, cast(LPARAM, hIcon))
                        SendMessageW(hwnd, WM_SETICON, ICON_BIG, cast(LPARAM, hIcon))
                     END IF
                  END IF
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_SIZE
         IF wParam <> SIZE_MINIMIZED THEN
            ' // Resize the buttons
            DIM pWindow AS CWindow PTR = AfxCWindowPtr(hwnd)
            IF pWindow THEN pWindow->MoveWindow GetDlgItem(hwnd, IDC_PICKDLG), pWindow->ClientWidth - 230, pWindow->ClientHeight - 50, 75, 23, CTRUE
            IF pWindow THEN pWindow->MoveWindow GetDlgItem(hwnd, IDCANCEL), pWindow->ClientWidth - 120, pWindow->ClientHeight - 50, 75, 23, CTRUE
         END IF

    CASE WM_DESTROY
         ' // Destroy the icon
         IF hIcon THEN DestroyIcon(hIcon)
          ' // End the application sending a WM_QUIT message
         PostQuitMessage(0)
         EXIT FUNCTION

   END SELECT

   ' // Process Windows messages
   FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


Paul Squires

Hi Jose,

I see that you are #Include the windowsx.bi file when you use AfxCtl.inc. The windowsx.bi file is not translated correctly in the latest FB distribution. Maybe you should code without using it?

#include once "win/windowsx.bi"

I made a cleaned/fixed up version of windowsx.bi and I manually include it my code (well, in WinFBE that is what I am doing). Of course using the windowsx.bi and my windowsxx.bi files together cause duplicate definition errors. So, at this time whenever I include your AfxWin.inc include, i get duplicate errors because of these two lines at the end of the file:

' // Other include files - Must go here for a matter of forward references
'#INCLUDE ONCE "Afx/AfxMenu.inc"
'#INCLUDE ONCE "Afx/AfxCtl.inc"

AfxCtl.inc includes windowsx.bi

Paul Squires
PlanetSquires Software

James Fuller

Paul,
  I just replaced the original with yours from your Fb Forum Post.
Is that one up to date?

James

Paul Squires

Yes, that one is up to date.
Paul Squires
PlanetSquires Software

José Roca

#13
Quote
' // Other include files - Must go here for a matter of forward references
'#INCLUDE ONCE "Afx/AfxMenu.inc"
'#INCLUDE ONCE "Afx/AfxCtl.inc"

Remove them. I will add them to my code when needed.

Quote
AfxCtl.inc includes windowsx.bi

Indeed. In AfxCtl.inc I only have added wrappers for the messages that are not covered by windowsx.bi and commctrl.bi. AFAIK the only problem are the message crackers, that I don't use. If I change the name to windowsxx.bi, then the code will fail if somebody that does not have your modified file tries to compile it. Maybe you should replace windows.bi with your include instead of using another name.

James Fuller

Jose,
  I am exploring CBStr and noticed there is not Len(gth) PROPERTY?

James