• Welcome to PlanetSquires Forums.
 

WinFBE using CWindow #8

Started by Paul Squires, June 20, 2016, 06:52:01 PM

Previous topic - Next topic

Paul Squires

Latest source and binaries attached.
Biggest change is the inclusion of Jose's source code template system.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

#1
We need to unscale the passed coordinates. Also some adjustments because of the change of window style. Looks fine at 192 DPI; check it in your system.


Function frmTemplates_Show (ByVal hParent As HWnd, ByVal x As Long, ByVal y As Long) As Long

   Dim pWindow As CWindow Ptr = New CWindow
   pWindow->DPI = AfxCWindowPtr(hParent)->DPI
   pWindow->Create(hParent, "Templates", @frmTemplates_WndProc, pWindow->UnScaleX(x) + 5, pWindow->UnscaleY(y) + 5, 420, 405, _
      WS_VISIBLE Or WS_CAPTION Or WS_POPUPWINDOW, WS_EX_WINDOWEDGE)
   pWindow->SetClientSize(415, 380)

   ' Set the small and large icon for the main window (must be set after main window is created)
   pWindow->BigIcon   =  LoadImage( pWindow->InstanceHandle, "IMAGE_MAINICON", IMAGE_ICON, 32, 32, LR_SHARED)
   pWindow->SmallIcon =  LoadImage( pWindow->InstanceHandle, "IMAGE_MAINICON", IMAGE_ICON, 16, 16, LR_SHARED)

   ' Add a listbox
   Dim hListBox As HWnd = pWindow->AddControl("ListBox", , IDC_FRMTEMPLATES_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, 399, 335, SWP_NOZORDER
   SendMessageW hListBox, LB_SETHORIZONTALEXTENT, Cast(WPARAM, 600 * pWindow->rxRatio), 0

   ' Add the buttons
   pWindow->AddControl("Button", , IDOK, "&OK", 245, 343, 74, 28, _
               WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_FLAT Or BS_DEFPUSHBUTTON, WS_EX_NOPARENTNOTIFY)
   pWindow->AddControl("Button", , IDCANCEL, "&Cancel", 333, 343, 74, 28, _
               WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_FLAT, WS_EX_NOPARENTNOTIFY)


this.FindReplace( "|", "" ) fails because FB strings are asciiz strings and it passes a null pointer instead of a pointer to an empty string. We could ulse a BSTR, but as your workaround works, it isn't needed.

What I can't find is why the view is not scrolled to the position of the caret. We are using SciMsg( m_pSci, SCI_GOTOPOS, newPos, 0) and SCI_GOTOPOS sets the caret at pos and scrolls the view to make the caret visible, if necessary. The purpose of "|" is to set a position where the view will be scrolled; otherwise, does not make sense.


Paul Squires

I believe the view is not scrolled into view because at the time that this.FindReplace is called, the Scintilla window is not display and the height and width of the Scintilla has not been set. So, I expect that Scintilla can't scroll because it has no window height to calculate whether to scroll or not. If you add the following at the end of clsDocument.DisplayStats then the window will scroll into view. That's because the window is sized and visible at that time.

   curPos = SciMsg( m_pSci, SCI_GETCURRENTPOS, 0, 0)
   SciMsg( m_pSci, SCI_GOTOPOS, curPos, 0)

I have attached a screenshot to show what the Templates window looks like on my screen with your measurement changes.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

Looks fine.

There is still an small DPI problem:

In ApplyProperties, you have some fixed values, e.g.


SciMsg( m_pSci, SCI_SETMARGINWIDTHN, 2, Iif(gConfig.FoldMargin, 16, 0) )


when  it should be


SciMsg( m_pSci, SCI_SETMARGINWIDTHN, 2, Iif(gConfig.FoldMargin, 16 * pWindow.rxRatio, 0) )


because of this, the folding symbols appear too small in my system (see capture).

We can't use fixed pixel values.

José Roca

You need also to change


   ''  INDENTATION GUIDES
   If gConfig.IndentGuides Then
      SciMsg( m_pSci, SCI_SETINDENTATIONGUIDES, CTrue, 0)
   Else
      SciMsg( m_pSci, SCI_SETINDENTATIONGUIDES, False, 0)
   End If


You're using True and the indentation guides aren't displayed.

You have to use CTrue.

Be careful with the boolean True because some third party controls such Scintilla, written in C, don't like -1 instead of 1.

José Roca

We were getting the rect of the toolbar, when we should ask for the rect of the rebar.


'                  SendMessageW(ptbn->hdr.hwndFrom, TB_GETRECT, ptbn->iItem, Cast(LPARAM, @rc))
                  SendMessageW(GetDlgItem(HWnd, IDC_FRMMAIN_REBAR), RB_GETRECT, 0, cast(LPARAM, @rc))


and


Function frmTemplates_Show (ByVal hParent As HWnd, ByVal x As Long, ByVal y As Long) As Long

   Dim pWindow As CWindow Ptr = New CWindow
   pWindow->DPI = AfxCWindowPtr(hParent)->DPI
   pWindow->Create(hParent, "Templates", @frmTemplates_WndProc, pWindow->UnScaleX(x), pWindow->UnscaleY(y), 420, 405, _
      WS_VISIBLE Or WS_CAPTION Or WS_POPUPWINDOW, WS_EX_WINDOWEDGE)
   pWindow->SetClientSize(415, 380)


Paul Squires

Thanks! I have all of these changes made now. I am working on the compile process and resulting display of warnings and errors. Hope to have that finished tonight and be able to post the source and binaries before I go to bed.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

Here is some code that I use in my PB editor to check if the the program that we are going to compile is already running.


' ========================================================================================
' // Get the full process image name
' ========================================================================================
FUNCTION FBSED_GetFullProcessImageName (BYREF pe32w AS PROCESSENTRY32W) AS WSTRING
   LOCAL hProcess AS DWORD
   LOCAL wszExeName AS WSTRINGZ * %MAX_PATH
   LOCAL dwSize AS DWORD
   hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION OR %PROCESS_VM_READ, 1, pe32w.th32ProcessID)
   IF hProcess THEN
      dwSize = %MAX_PATH
      IF ISTRUE QueryFullProcessImageNameW(hProcess, 0, wszExeName, dwSize) THEN
         FUNCTION = wszExeName
      END IF
      CloseHandle hProcess
   END IF
END FUNCTION
' ========================================================================================

' ========================================================================================
' // Checks if the program that we are going to compile is already running
' ========================================================================================
FUNCTION FBSED_IsProcessRunning(BYVAL bstrExeFileName AS WSTRING) AS LONG

   LOCAL hSnapShot AS DWORD
   LOCAL pe32w AS PROCESSENTRY32W

   pe32w.dwSize = SIZEOF(pe32w)
   bstrExeFileName = UCASE$(bstrExeFileName)
   hSnapShot = CreateToolhelp32Snapshot(%TH32CS_SNAPPROCESS, 0)
   IF hSnapShot <> %INVALID_HANDLE_VALUE THEN
      IF ISTRUE Process32First(hSnapShot, pe32w) THEN
         IF UCASE$(FBSED_GetFullProcessImageName(pe32w)) = bstrExeFileName THEN
            FUNCTION = %TRUE
         ELSE
            WHILE Process32Next(hSnapShot, pe32w) > 0
               IF UCASE$(FBSED_GetFullProcessImageName(pe32w)) = bstrExeFileName THEN
                  FUNCTION = %TRUE
                  EXIT DO
               END IF
            WEND
         END IF
      END IF
   END IF
   CloseHandle hSnapShot

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


Paul Squires

Quote from: Jose Roca on June 21, 2016, 05:48:35 PM
Here is some code that I use in my PB editor to check if the the program that we are going to compile is already running.


' ========================================================================================
' // Get the full process image name
' ========================================================================================
FUNCTION FBSED_GetFullProcessImageName (BYREF pe32w AS PROCESSENTRY32W) AS WSTRING
   LOCAL hProcess AS DWORD
   LOCAL wszExeName AS WSTRINGZ * %MAX_PATH
   LOCAL dwSize AS DWORD
   hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION OR %PROCESS_VM_READ, 1, pe32w.th32ProcessID)
   IF hProcess THEN
      dwSize = %MAX_PATH
      IF ISTRUE QueryFullProcessImageNameW(hProcess, 0, wszExeName, dwSize) THEN
         FUNCTION = wszExeName
      END IF
      CloseHandle hProcess
   END IF
END FUNCTION
' ========================================================================================

' ========================================================================================
' // Checks if the program that we are going to compile is already running
' ========================================================================================
FUNCTION FBSED_IsProcessRunning(BYVAL bstrExeFileName AS WSTRING) AS LONG

   LOCAL hSnapShot AS DWORD
   LOCAL pe32w AS PROCESSENTRY32W

   pe32w.dwSize = SIZEOF(pe32w)
   bstrExeFileName = UCASE$(bstrExeFileName)
   hSnapShot = CreateToolhelp32Snapshot(%TH32CS_SNAPPROCESS, 0)
   IF hSnapShot <> %INVALID_HANDLE_VALUE THEN
      IF ISTRUE Process32First(hSnapShot, pe32w) THEN
         IF UCASE$(FBSED_GetFullProcessImageName(pe32w)) = bstrExeFileName THEN
            FUNCTION = %TRUE
         ELSE
            WHILE Process32Next(hSnapShot, pe32w) > 0
               IF UCASE$(FBSED_GetFullProcessImageName(pe32w)) = bstrExeFileName THEN
                  FUNCTION = %TRUE
                  EXIT DO
               END IF
            WEND
         END IF
      END IF
   END IF
   CloseHandle hSnapShot

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



Thanks Jose, I believe that you sent this to me a few months ago. I never ended up using it because I believe that it required Vista or higher and I still had a large number of FireFly customers using WinXP. I will add this code to WinFBE tomorrow.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

I think that XP is too outdated to continue supporting it. Many things in the CWindow framework, beginning with High DPI, aren't supported by this OS (it supports large fonts, that isn't quite the same).

You're already using code that requires Vista or superior, like the IFileDialog interface.

People isn't going to use 96 DPI forever, and when they will have to use a higher DPI they will realize how awful their applications look and behave. We must no longer think in terms of pixels, but of DIPs (device independent units).


Paul Squires

I agree 100%. I have no desire to support WinXP whatsoever especially for all my new projects and this WinFBE editor.

However, with Firefly I had many customers who continued to use WinXP and I didn't want to break the program for them.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

Here is the FB translation of your IsProcessRunning code. Seems to work perfectly.


#Include Once "win\TlHelp32.bi"

' ========================================================================================
' Get the full process image name
' ========================================================================================
Function GetProcessImageName( ByVal pe32w As PROCESSENTRY32W Ptr ) As WString Ptr
   Dim dwSize As Long
   Dim hProcess As HANDLE
   Dim wszExeName As WString * MAX_PATH
   hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 1, pe32w->th32ProcessID)
   If hProcess Then
      dwSize = MAX_PATH
      If QueryFullProcessImageNameW( hProcess, 0, @wszExeName, @dwSize ) Then
         Function = @wszExeName
      End If
      CloseHandle hProcess
   End If
End Function


' ========================================================================================
' Checks if the program that we are going to compile is already running
' ========================================================================================
Function IsProcessRunning( ByVal pwszExeFileName As WString Ptr ) As BOOLEAN

   Dim hSnapShot As HANDLE
   Dim pe32w As PROCESSENTRY32W

   Dim wszExeFileName As WString * MAX_PATH = Ucase(*pwszExeFileName)

   pe32w.dwSize = Sizeof(pe32w)
   hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)

   If hSnapShot <> INVALID_HANDLE_VALUE Then
      If Process32First(hSnapShot, @pe32w) Then
         If Ucase(*GetProcessImageName(@pe32w)) = wszExeFileName Then
            Function = True
         Else
            Do While Process32Next(hSnapShot, @pe32w) > 0
               If Ucase(*GetProcessImageName(@pe32w)) = wszExeFileName Then
                  Function = True
                  Exit Do
               End If
            Loop
         End If
      End If
   End If
   CloseHandle hSnapShot

End Function

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

This part must be changed because it is returning a pointer to a local variable. We have to pass wszExeName as a byref parameter that will receive the path. In the PB version, I'm returning a BSTR because the PB compiler has support for them an will return a copy.


' ========================================================================================
' Get the full process image name
' ========================================================================================
Function GetProcessImageName( ByVal pe32w As PROCESSENTRY32W Ptr ) As WString Ptr
   Dim dwSize As Long
   Dim hProcess As HANDLE
   Dim wszExeName As WString * MAX_PATH
   hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 1, pe32w->th32ProcessID)
   If hProcess Then
      dwSize = MAX_PATH
      If QueryFullProcessImageNameW( hProcess, 0, @wszExeName, @dwSize ) Then
         Function = @wszExeName
      End If
      CloseHandle hProcess
   End If
End Function


Paul Squires

hmmmm.... yes, that sounds right. I wonder why it was working for me. The allocated memory for that local variable must still have been valid after the return from the function. Just lucky I guess. I will change the code to pass it by reference. I guess dim'ing wszExeName as static probably would work also.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

Here is the corrected version:


#Include Once "win\TlHelp32.bi"

' ========================================================================================
' Get the full process image name
' ========================================================================================
Function GetProcessImageName( ByVal pe32w As PROCESSENTRY32W Ptr, _
                              ByVal pwszExeName As WString Ptr _
                              ) As Long
   Dim dwSize As Long
   Dim hProcess As HANDLE
   hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 1, pe32w->th32ProcessID)
   If hProcess Then
      dwSize = MAX_PATH
      QueryFullProcessImageNameW( hProcess, 0, pwszExeName, @dwSize )
      CloseHandle hProcess
   End If
End Function


' ========================================================================================
' Checks if the program that we are going to compile is already running
' ========================================================================================
Function IsProcessRunning( ByVal pwszExeFileName As WString Ptr ) As BOOLEAN

   Dim hSnapShot As HANDLE
   Dim pe32w As PROCESSENTRY32W

   Dim wszExeFileName As WString * MAX_PATH = Ucase(*pwszExeFileName)
   Dim wszExeProcessName As WString * MAX_PATH

   pe32w.dwSize = Sizeof(pe32w)
   hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)

   If hSnapShot <> INVALID_HANDLE_VALUE Then
      If Process32First(hSnapShot, @pe32w) Then
         GetProcessImageName( @pe32w, @wszExeProcessName )
         If Ucase(wszExeProcessName) = wszExeFileName Then
            Function = True
         Else
            Do While Process32Next(hSnapShot, @pe32w) > 0
               GetProcessImageName( @pe32w, @wszExeProcessName )
               If Ucase(wszExeProcessName) = wszExeFileName Then
                  Function = True
                  Exit Do
               End If
            Loop
         End If
      End If
   End If
   CloseHandle hSnapShot

End Function


Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer