• Welcome to PlanetSquires Forums.
 

WinFBE using CWindow #7

Started by Paul Squires, June 19, 2016, 09:12:37 PM

Previous topic - Next topic

Paul Squires

Latest source and binaries are attached.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

#1
Support for PB-like templates:

In modToolbar.inc change


   Toolbar_AddButton hToolBar, i, IDM_FILENEW, 0, TBSTYLE_DROPDOWN


to add a dropdown arrow to the New File item.

In frmMain_OnNotify add the following code to process the dropdown notification:


   SELECT CASE pNMHDR->idFrom
      CASE IDC_FRMMAIN_TOOLBAR
         DIM ptbn AS TBNOTIFY PTR = CAST(TBNOTIFY PTR, pNMHDR)
         IF ptbn->hdr.code = TBN_DROPDOWN THEN
            SELECT CASE ptbn->iItem
               ' // Dropdown new file menu
               CASE IDM_FILENEW
                  DIM rc AS RECT
                  SendMessageW(ptbn->hdr.hwndFrom, TB_GETRECT, cast(WPARAM, IDC_FRMMAIN_TOOLBAR), CAST(LPARAM, @rc))
                  MapWindowPoints(ptbn->hdr.hwndFrom, HWND_DESKTOP, CAST(POINT PTR, @rc), 2)
                  frmTemplates_Show(hwnd, rc.Left, rc.Bottom)
            END SELECT
         END IF
   END SELECT


Module for templates loading:


CONST IDC_TEMPLATES_LISTBOX = 101

' ========================================================================================
' Templates popup dialog
' ========================================================================================
FUNCTION frmTemplates_Show (BYVAL hParent AS HWND, BYVAL x AS LONG, BYVAL y AS LONG) AS LONG

   DIM pWindow AS CWindow
   pWindow.DPI = AfxCWindowPtr(hParent)->DPI
   pWindow.Create(hParent, "Templates", @frmTemplates_WndProc, x + 5, y + 5, 432, 422, _
      WS_VISIBLE OR WS_CAPTION OR WS_POPUPWINDOW OR WS_THICKFRAME, WS_EX_WINDOWEDGE)

   ' // Add a listbox
   DIM hListBox AS HWND = pWindow.AddControl("ListBox", , IDC_TEMPLATES_LISTBOX, "", _
      WS_CHILD OR WS_VISIBLE OR WS_HSCROLL OR WS_VSCROLL OR WS_BORDER OR WS_TABSTOP OR _
      LBS_STANDARD OR LBS_HASSTRINGS OR LBS_SORT OR LBS_NOTIFY OR LBS_NOINTEGRALHEIGHT, WS_EX_CLIENTEDGE)
   pWindow.SetWindowPos hListBox, NULL, 8, 8, 400, 337, SWP_NOZORDER
   SendMessageW hListBox, LB_SETHORIZONTALEXTENT, cast(WPARAM, 600 * pWindow.rxRatio), 0

   ' // Add the buttons
   pWindow.AddControl("Button", , IDOK, "&Ok", 245, 353, 75, 23, WS_CHILD OR WS_VISIBLE OR WS_TABSTOP OR BS_FLAT OR BS_DEFPUSHBUTTON, WS_EX_NOPARENTNOTIFY)
   pWindow.AddControl("Button", , IDCANCEL, "&Cancel", 333, 353, 75, 23, WS_CHILD OR WS_VISIBLE OR WS_TABSTOP OR BS_FLAT, WS_EX_NOPARENTNOTIFY)

   ' // Search templates
   DIM hSearch as HANDLE, WFD AS WIN32_FIND_DATAW, FileNo AS LONG, nType AS LONG, nItem AS LONG
   DIM wszPath AS WSTRING * MAX_PATH, wszCurPath AS WSTRING * MAX_PATH, wszText AS WSTRING * 260
   DIM wszFullPath AS WSTRING * MAX_PATH * 2, idx AS LONG, nLin AS LONG
   wszPath = ExePath & "\Templates\"
   wszCurPath = wszPath & "*.fbtpl"

   ' // Count the number of files and dimension the array
   ' // REDIM PRESERVE causes problems
   DIM nCount AS LONG
   hSearch = FindFirstFileW(wszCurPath, @WFD)
   IF hSearch <> INVALID_HANDLE_VALUE THEN
      DO
         IF (WFD.dwFileAttributes AND FILE_ATTRIBUTE_DIRECTORY) <> FILE_ATTRIBUTE_DIRECTORY THEN
            nCount +=1
         END IF
      LOOP WHILE FindNextFileW(hSearch, @WFD)
      FindClose(hSearch)
   END IF
   ' // Dimension the array
   IF nCount = 0 THEN EXIT FUNCTION
   DIM rgwszPaths(nCount - 1) AS WSTRING * MAX_PATH
   idx = 0

   ' // Find the files
   hSearch = FindFirstFileW(wszCurPath, @WFD)
   IF hSearch <> INVALID_HANDLE_VALUE THEN
      DO
         IF (WFD.dwFileAttributes AND FILE_ATTRIBUTE_DIRECTORY) <> FILE_ATTRIBUTE_DIRECTORY THEN
            wszFullPath = wszPath & WFD.cFileName
            ' // Get the description
            FileNo = FREEFILE
            OPEN wszFullPath FOR INPUT AS #FileNo
            IF ERR = 0 THEN
               nLin = 0
               DO UNTIL EOF(FileNo)
                  LINE INPUT #FileNo, wszText
                  nLin += 1
                  IF nLin = 1 THEN nType = VAL(wszText)
                  IF nType < 1 OR nType > 2 THEN EXIT DO
                  IF nType = 1 AND nLin = 3 THEN EXIT DO
                  IF nType = 2 AND nLin = 4 THEN EXIT DO
               LOOP
               CLOSE FileNo
               ' // Display the description in the listbox
               nItem = SendMessageW(hListBox, LB_ADDSTRING, 0, cast(LPARAM, @wszText))
               ' // Store the full path in the array
               rgwszPaths(idx) = wszFullPath
               ' // Store a pointer to the element of the array in the listbox item
               SendMessageW hListBox, LB_SETITEMDATA, nItem, cast(LPARAM, VARPTR(rgwszPaths(idx)))
               idx += 1
               IF idx > UBOUND(rgwszPaths) THEN EXIT DO
            END IF
         END IF
      LOOP WHILE FindNextFileW(hSearch, @WFD)
      FindClose(hSearch)
   END IF

   ' / Process Windows messages
   FUNCTION = pWindow.DoEvents

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

' ========================================================================================
' Templates window procedure
' ========================================================================================
FUNCTION frmTemplates_WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

   SELECT CASE uMsg

      CASE WM_CREATE
         ' Disable parent window to make popup window modal
         EnableWindow GetParent(hwnd), FALSE
         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
            CASE IDOK
               IF HIWORD(wParam) = BN_CLICKED THEN
                  ' // Let the IDC_TEMPLATES_LISTBOX message to process it
                  SendMessageW hwnd, WM_COMMAND, MAKELONG(IDC_TEMPLATES_LISTBOX, LBN_DBLCLK), 0
                  EXIT FUNCTION
               END IF
            CASE IDC_TEMPLATES_LISTBOX
               SELECT CASE HIWORD(wParam)
                  CASE LBN_DBLCLK
                     ' // Get the handle of the Listbox
                     DIM hListBox AS HWND = GetDlgItem(hwnd, IDC_TEMPLATES_LISTBOX)
                     ' // Get the current selection
                     DIM curSel AS LONG = SendMessageW(hListBox, LB_GETCURSEL, 0, 0)
                     IF curSel = LB_ERR THEN EXIT FUNCTION
                     ' // Get the stored index
                     DIM pwszPath AS WSTRING PTR = cast(WSTRING PTR, SendMessageW(hListBox, LB_GETITEMDATA, cast(WPARAM, curSel), 0))
                     IF pwszPath = LB_ERR THEN EXIT FUNCTION
                     ' // Open the template
                     IF pwszPath THEN
                        ' // TODO: Create a new Scintilla control
                        ' // TODO: Load the file
                        ' // TODO: Search for "|", replace it with "" and position the caret in that place
                        ' // Replace the marker with an empty space
                        ' SCIP_FindReplace(pSci, "|", "")
                        ' // Set the state of the document as unmodified
                        ' SCIP_SetSavePoint(pSci)
                        ' // The SCIP_xxx functions are located in the SciCtrl.inc file of the PowerBASIC headers
                     END IF
                     ' // Close the dialog
                     SendMessageW hwnd, WM_CLOSE, 0, 0
                     EXIT FUNCTION
               END SELECT
         END SELECT

      CASE WM_CLOSE
         ' // Enables parent window keeping parent's zorder
         EnableWindow GetParent(hwnd), CTRUE
         ' // Don't exit; let DefWindowProcW perform the default action

    CASE WM_DESTROY
         ' // End the application by sending an WM_QUIT message
         PostQuitMessage(0)
         EXIT FUNCTION

   END SELECT

   ' // Default processing of Windows messages
   FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)

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


The attached file contains many templates.

José Roca

This is the TODO part:


                     ' // Open the template
                     IF pwszPath THEN
                        ' // TODO: Create a new Scintilla control
                        ' // TODO: Load the file
                        ' // TODO: Search for "|", replace it with "" and position the caret in that place
                        ' // Replace the marker with an empty space
                        ' SCIP_FindReplace(pSci, "|", "")
                        ' // Set the state of the document as unmodified
                        ' SCIP_SetSavePoint(pSci)
                        ' // The SCIP_xxx functions are located in the SciCtrl.inc file of the PowerBASIC headers
                     END IF


José Roca

This is how will look, more or less.

José Roca

Note: Load the template as Untitled<number>.bas.

Paul Squires

#5
Thanks Jose :)   I have most of the code implemented now. Only had to do some changes in order to make it fit within the style I'm using (message crackers, etc). I also had to make the following small change. You used the toolbar identifier instead of the toolbar button identifier.

Instead of:
   SendMessageW(ptbn->hdr.hwndFrom, TB_GETRECT, Cast(WPARAM, IDC_FRMMAIN_TOOLBAR), Cast(LPARAM, @rc))
Use:
    SendMessageW(ptbn->hdr.hwndFrom, TB_GETRECT, IDM_FILENEW, Cast(LPARAM, @rc))

I also removed the WS_THICKFRAME style from the Templates window.

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

#6
I coded it as a separate test without a toolbar and part of the code was theoretical. My major concern was to build the array of paths. With REDIM PRESERVE apparently the memory changed and some of the pointers stored in the listbox where no longer valid. This is why I first get the number of files to dimension the array.

Paul Squires

Sounds good. I was wondering why you did that with the array. Better safe than sorry if REDIM PRESERVE is causing a problem.
The only other difference I coded was to NOT set the save point after loading the template file. This keeps the file buffer dirty (and displays the "*" indicator) so that the user can either save the file as the default "UNTITLED1.BAS", "UNTITLED2.BAS", "UNTITLED3.BAS", etc.. or Save As a different name.

The templating system you have made is pretty cool.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

#8
> The only other difference I coded was to NOT set the save point after loading the template file.

This is because my editor allows to compile and run code that does not use resources without saving it first. The editor saves it to a temporary file before compiling it. If I don't set the save point, the editor will ask me to save the file. It is very useful when doing small tests.


José Roca

The number 2 indicates the number of lines before the description:

FBGUI
.bas

FBGUI means that it is a gui program, and FBCON that it is a console program. I use it to know if I have to call the compiler with the gui or console switch.

The .bas line is to indicate the type of program: .bas for basic code, .xml for manifests, etc.