• Welcome to PlanetSquires Forums.
 

Why do I always get the wrong HWND back?

Started by jermy, January 28, 2019, 12:52:52 PM

Previous topic - Next topic

jermy

Hi Dear people,

Something goes wrong with this code, I can not get a correct HWND back


'--------------------------------------------------------------------------------
Function FORM1_COMMAND1_BN_CLICKED ( _
                                   ControlIndex     as Long, _      ' index in Control Array
                                   hWndForm         as HWnd, _      ' handle of Form
                                   hWndControl      as HWnd, _      ' handle of Control
                                   idButtonControl  as Long   _     ' identifier of button
                                   ) as Long
Dim hProcessID as Long 'DWORD
Dim hWndApp as HWnd   

hProcessID = GetCurrentProcessId()

hWndApp = GethWndFromProcessID(hProcessID)

Print "hProcessID "; hProcessID

Print " hWndApp "; hWndApp
  '   SetWindowText(hWndApp, "test 1 ")  ' & Cast(String, hWndApp)
Print " HWND_FORM1 "; HWND_FORM1
   '  SetWindowText(HWND_FORM1, "test 2 ")  ' & Cast(String, hWndApp)

   Function = 0   ' change according to your needs
End Function


Function GethWndFromProcessID(ByVal hProcessIDToFind as Long) as HWnd

    Dim hWndDesktop as HWnd
    Dim hWndChild as HWnd
    Dim hWndChildProcessID as Long
   
    On Local Error Goto GethWndFromProcessID_Error
   
   'get the handle to the desktop
    hWndDesktop = GetDesktopWindow()
   
   'get the first child under the desktop
    hWndChild = GetWindow(hWndDesktop, GW_CHILD)
   
   'hwndchild will = 0 when no more child windows are found
    Do While hWndChild <> 0
   
       'get the ThreadProcessID of the window
         GetWindowThreadProcessId(hWndChild, @hWndChildProcessID)
       
       'if it matches the target, exit returning that value
        If hWndChildProcessID = hProcessIDToFind Then
            Exit Do
        End If
       
       'not found, so get the next hwnd
        hWndChild = GetWindow(hWndChild, GW_HWNDNEXT)
       
    Loop
   
    Function = hWndChild   ' change according to your needs             

Exit Function

GethWndFromProcessID_Error:
    GethWndFromProcessID = 0
    Exit Function
   
End Function


anyone an idea why it goes wrong?

José Roca

It works using my AfxGethWndFromPID wrapper function:


hWndApp = AfxGethWndFromPID(GetCurrentProcessId)


raymw

Hi Jermy,
I don't really know what the correct hwnd should be, but your sw gives a result that looks OK. The values change if I open other windows before running the code.

jermy

Quote from: raymw on January 28, 2019, 02:56:51 PM
Hi Jermy,
I don't really know what the correct hwnd should be, but your sw gives a result that looks OK. The values change if I open other windows before running the code.

the value hWndApp should be the same as HWND_FORM1
if you use SetWindowText with hWndApp you will see that nothing happens, with HWND_FORM1 you change the caption


      SetWindowText(hWndApp, "test 1 " & hWndApp)

    ' SetWindowText(HWND_FORM1, "test 2 " & HWND_FORM1) 



jermy

finally found it,

he returned the HWND from the first child window that he found, with GetParent in between he works


Function GethWndFromProcessID(ByVal hProcessIDToFind as Long) as HWnd

    Dim as HWnd hWndDesktop, hWndChild
    Dim hWndChildProcessID as Long
   
   'get the handle to the desktop
    hWndDesktop = GetDesktopWindow()
   
   'get the first child under the desktop
    hWndChild = GetWindow(hWndDesktop, GW_CHILD)
   
   'hwndchild will = 0 when no more child windows are found
    Do While hWndChild <> 0
       'See if this window has a parent. If not it is a top-level window.
     If GetParent(hWndChild) = 0 Then

       'get the ThreadProcessID of the window
         GetWindowThreadProcessId(hWndChild, @hWndChildProcessID)
       
       'if it matches the target, exit returning that value
        If hWndChildProcessID = hProcessIDToFind Then
            Exit Do
        End If

     End If 
       'not found, so get the next hwnd
        hWndChild = GetWindow(hWndChild, GW_HWNDNEXT)
    Loop
   
    Function = hWndChild   ' change according to your needs             
   
End Function

José Roca

You would have saved time if you had used my AfxGethWndFromPID function (in AfxWin.inc):


' ========================================================================================
' Retrieves a window handle given it's process identifier
' ========================================================================================
PRIVATE FUNCTION AfxGethWndFromPID (BYVAL PID AS DWORD) AS HWND
   DIM dwPID AS DWORD, dwThreadID AS DWORD
   ' // Get the first window handle
   DIM hwnd AS HWND = FindWindowW(NULL, NULL)
   ' // Enumerate all the windows
   WHILE hwnd <> NULL
      ' // If the parent window is NULL, it's a top level window
      IF GetParent(hwnd) = NULL THEN
         ' // Get it's process id
         dwThreadID = GetWindowThreadProcessId(hwnd, @dwPID)
         IF dwPID = PID THEN
            ' // We have found it
            FUNCTION = hwnd
            EXIT WHILE
         END IF
      END IF
      ' // Get the next window handle
      hwnd = GetWindow(hwnd, GW_HWNDNEXT)
   WEND
END FUNCTION
' ========================================================================================


jermy

#6
QuoteYou would have saved time if you had used my AfxGethWndFromPID function (in AfxWin.inc):

The sdk is very interesting, that is for hundreds of hours of programming work.

tnx for sharing.

Paul Squires

From my perspective, if anyone is a FreeBasic Windows programmer you NEED to be using Jose's WinFBX framework. You are wasting time and energy otherwise.  :)
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

jermy

#8
I cant include AfxWin.inc, the compiler gives errors
I've tried it with a new empty project, do i need some extra compiler switches?

FreeBASIC Compiler - Version 1.05.0 (01-31-2016), built for win64 (64bit)
Copyright (C) 2004-2016 The FreeBASIC development team.
standalone
target:       win64, x86-64, 64bit
compiling:    CODEGEN_PROJECT1_MAIN.bas -o CODEGEN_PROJECT1_MAIN.c (main module)
C:\FreeBasic\FreeBASIC-1.05.0-win64\inc\Afx\AfxWin.inc(1204) warning 4(1): Suspicious pointer assignment
C:\FreeBasic\FreeBASIC-1.05.0-win64\inc\Afx\AfxWin.inc(1255) warning 4(1): Suspicious pointer assignment
CODEGEN_PROJECT1_MAIN.bas(147) error 4: Duplicated definition in 'Function AfxScaleX (BYVAL cx AS SINGLE) AS SINGLE'
CODEGEN_PROJECT1_MAIN.bas(163) error 4: Duplicated definition in 'Function AfxScaleY (BYVAL cy AS SINGLE) AS SINGLE'


or is the include file not compatible with firefly?

José Roca

Forget what I said. I thought that you were using WinFBE, not FireFly.

From now on I will not answer questions if the tool being used is not clearly specified.


Paul Squires

A long time ago, I hard coded AfxScaleX and AfxScaleY into the code generation of FireFly. It was needed to help with high dpi resolution code generation. It is obviously interfering now with Jose's includes. Not much you can do now other than manually modifying Jose's AfxWin.inc file to comment out those two functions.

FireFly is horrible on high dpi aware displays. The sooner I finish writing the WinFBE visual designer, the better.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer