Announcement

Collapse
No announcement yet.

Window Handle

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Window Handle

    This may be an answer of "NO" but I thought I would ask anyways.
    Is there a way to find the "Windows Handle" of a Dialog or Window that I created in one function so that it can be used in other functions? Without declaring my variable as global?....or IE: I know the Equates value for the Window, but if I need to get the Windows Handle outside the function it was created in, is there a way?

    I know there are API's for current Window, next window etc, but to my knowledge they are for use of enumerating Windows. Which does me no good unless I know the Windows Handle I am looking for.

    For example from PbForms
    Code:
    #PBFORMS CREATED V1.51
    '------------------------------------------------------------------------------
    ' The first line in this file is a PB/Forms metastatement.
    ' It should ALWAYS be the first line of the file. Other   
    ' PB/Forms metastatements are placed at the beginning and 
    ' end of "Named Blocks" of code that should be edited     
    ' with PBForms only. Do not manually edit or delete these 
    ' metastatements or PB/Forms will not be able to reread   
    ' the file correctly.  See the PB/Forms documentation for 
    ' more information.                                       
    ' Named blocks begin like this:    #PBFORMS BEGIN ...     
    ' Named blocks end like this:      #PBFORMS END ...       
    ' Other PB/Forms metastatements such as:                  
    '     #PBFORMS DECLARATIONS                               
    ' are used by PB/Forms to insert additional code.         
    ' Feel free to make changes anywhere else in the file.    
    '------------------------------------------------------------------------------
    
    #COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN INCLUDES 
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #PBFORMS END INCLUDES
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN CONSTANTS 
    %IDD_DIALOG1 = 101     '<--- I know this value, but Windows Handle not known until the Window is created
    #PBFORMS END CONSTANTS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                ' Initialization handler
    
            CASE %WM_NCACTIVATE
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CBWPARAM THEN
                    ' Save control focus
                    hWndSaveFocus = GetFocus()
                ELSEIF hWndSaveFocus THEN
                    ' Restore control focus
                    SetFocus(hWndSaveFocus)
                    hWndSaveFocus = 0
                END IF
    
            CASE %WM_COMMAND
                ' Process control notifications
                SELECT CASE AS LONG CBCTL
    
                END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
        LOCAL hDlg  AS DWORD     '<---Only valid in this function unless I make it global?
    
        DIALOG NEW hParent, "Dialog1", 70, 70, 201, 121, %WS_POPUP OR %WS_BORDER _
            OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
            %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
            %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
            %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
            %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
    #PBFORMS END DIALOG
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    '------------------------------------------------------------------------------
    Any way to do what I am thinking? (probable answer is "NO") or in this case I am most likely stuck with a Global variable to hold the value?

    One side question that could be interesting. Is it better to declare the variable for the Windows Handle to be declared as DWORD or as LONG?
    From my knowledge both SDK and DDT return %NULL if the window could not be created, or the Handle to the Window if it could. But I never checked to see if the Handle value was always in the range of a DWORD or a LONG?
    (maybe another mute question, but "Inquiring Minds what to know")
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

  • #2
    Any way to do what I am thinking? (probable answer is "NO") or in this case I am most likely stuck with a Global variable to hold the value?
    The answer is yes.
    Use the EnumWindows function.
    You can simplify the process by assigning a GUID to the window as a property and just checking for that using GetProp.

    One side question that could be interesting. Is it better to declare the variable for the Windows Handle to be declared as DWORD or as LONG?
    They are DWORDs, but you can use either long or dword since failure is indicated by a zero value.
    Dominic Mitchell
    Phoenix Visual Designer
    http://www.phnxthunder.com

    Comment


    • #3
      One more way...

      Code:
      #COMPILE EXE '#Win 8.04#
      #DIM ALL
      #REGISTER NONE
      #INCLUDE "Win32Api.inc" '#2005-01-27#
       
      %Label1   = 101
      %Label2   = 102
      %Button1  = 201
      '______________________________________________________________________________
       
      CALLBACK FUNCTION DlgProc2
       LOCAL hMainDlg AS DWORD
       
       SELECT CASE CBMSG
       
         CASE %WM_INITDIALOG
           DIALOG GET USER CBHNDL, 1 TO hMainDlg
           CONTROL SET TEXT CBHNDL, %Label1, "Main handle is " & HEX$(hMainDlg)
           PostMessage hMainDlg, %WM_USER + 500, CBHNDL, 0
       
        END SELECT
       
      END FUNCTION
      '______________________________________________________________________________
       
      FUNCTION Dialog2(hMainDlg AS DWORD) AS LONG
       LOCAL hChildDlg AS DWORD
       
       DIALOG NEW hMainDlg ,"Child dialog", , , 175, 75, _
                  %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, 0 TO hChildDlg
       CONTROL ADD LABEL, hChildDlg, %Label1, "Label 2", 55, 30, 90, 12
       DIALOG SET USER hChildDlg, 1, hMainDlg
       DIALOG SHOW MODAL hChildDlg CALL DlgProc2
       
      END FUNCTION
      '______________________________________________________________________________
       
      CALLBACK FUNCTION DlgProc
       
       SELECT CASE CBMSG
       
         CASE %WM_COMMAND
           SELECT CASE LOWRD(CBWPARAM)
             CASE %Button1
               IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                 Dialog2(CBHNDL)
               END IF
           END SELECT
       
         CASE %WM_USER + 500
           CONTROL SET TEXT CBHNDL, %Label1, "Child handle is " & HEX$(CBWPARAM)
       
        END SELECT
       
      END FUNCTION
      '______________________________________________________________________________
       
      FUNCTION PBMAIN()
       LOCAL hMainDlg AS DWORD
       
       DIALOG NEW %HWND_DESKTOP ,"Main dialog", , , 200, 170, _
                  %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, 0 TO hMainDlg
       SetClassLong hMainDlg, %GCL_HICON, LoadIcon(BYVAL %NULL, BYVAL %IDI_INFORMATION) 'Set a nice icon
       CONTROL ADD LABEL, hMainDlg, %Label1,  "Child handle", 15, 15, 170, 15
       CONTROL ADD BUTTON, hMainDlg, %Button1, "Child", 155, 145, 35, 15
       DIALOG SHOW MODAL hMainDlg CALL DlgProc
       
      END FUNCTION
      '______________________________________________________________________________
      Last edited by Pierre Bellisle; 14 Dec 2007, 08:46 PM.

      Comment


      • #4
        Thank you Pierre,
        I wonder if there is a SDK equivalent to "DIALOG GET USER" or if it is a Compiler thing?

        @Dominic
        I suppose I could do a GUID thing, but always avoided them from my VB days and using OCX's, unless I am mistaken on that concept?
        Engineer's Motto: If it aint broke take it apart and fix it

        "If at 1st you don't succeed... call it version 1.0"

        "Half of Programming is coding"....."The other 90% is DEBUGGING"

        "Document my code????" .... "WHYYY??? do you think they call it CODE? "

        Comment


        • #5
          Originally posted by Cliff Nichols View Post
          I wonder if there is a SDK equivalent to DIALOG GET USER" or if it is a Compiler thing?
          See SetProp, GetProp and RemoveProp
          kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

          Comment


          • #6
            I suppose I could do a GUID thing, but always avoided them from my VB days and using OCX's, unless I am mistaken on that concept?
            A GUID has nothing to do with OCX's in this case. It is just one way to uniquely identify a window.
            This avoids the need to check for window class, or caption, or both.

            One area where uniquely identifying a window comes in handy, is when enumerating controls on a window.
            Many controls usually consist of a container with embedded controls. These complex or compound controls`
            can cause problems when using the EnumChildWindows function. Uniquely identifying the control is the only
            nontrivial method that can be used to tell whether the control passed to the application-defined callback
            is one you created.
            Dominic Mitchell
            Phoenix Visual Designer
            http://www.phnxthunder.com

            Comment


            • #7
              >> I wonder if there is a SDK equivalent to DIALOG GET USER" or if it is a Compiler thing?
              > See SetProp, GetProp and RemoveProp

              See also GetWindowLong[Ptr], SetWindowLong[Ptr] functions.

              MCM
              Michael Mattias
              Tal Systems Inc. (retired)
              Racine WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                If you know the control id of a window (and you've got to know it cuz you had to set it to create the window), GetDlgItem(hParent,CtrlID) will return the hWnd. The complement to this function seems to be GetDlgCtrlID(hWnd), which, if you know the hWnd, will return the CtrlID.
                Fred
                "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                Comment


                • #9
                  Couldn't Get it

                  I tried many ways, but still could not "Find" the Windows Handle without already knowing the Windows Handle that I was trying to find.

                  So I came up with my own way, that seems to work and eliminates my need for a global variable for the Windows Handle.

                  Although I am still interested if someone can show me a working example Api functions I am fairly satisfied with the below code (unless I am breaking some rule that I have not thought of yet?)

                  Code:
                  #COMPILE EXE
                  #DIM ALL
                  #INCLUDE "WIN32API.INC"
                  %IDD_DIALOG1 =  101
                  %IDC_BUTTON1 = 1001
                  DECLARE FUNCTION PBMAIN()
                  DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
                  DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                  DECLARE FUNCTION SetGetDlg(BYREF SetHwndDlg AS DWORD, BYREF GetHwndDlg AS DWORD)AS DWORD
                  
                  FUNCTION PBMAIN()
                      ShowDIALOG1 %HWND_DESKTOP
                  END FUNCTION
                  
                  CALLBACK FUNCTION ShowDIALOG1Proc()
                      SELECT CASE AS LONG CBMSG
                          CASE %WM_INITDIALOG
                          CASE %WM_NCACTIVATE
                              STATIC hWndSaveFocus AS DWORD
                              IF ISFALSE CBWPARAM THEN
                                  ' Save control focus
                                  hWndSaveFocus = GetFocus()
                              ELSEIF hWndSaveFocus THEN
                                  ' Restore control focus
                                  SetFocus(hWndSaveFocus)
                                  hWndSaveFocus = 0
                              END IF
                  
                          CASE %WM_COMMAND
                              ' Process control notifications
                              SELECT CASE AS LONG CBCTL
                                  CASE %IDC_BUTTON1
                                      IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                  
                                           LOCAL TempSetDlg AS DWORD
                                           LOCAL TempGetDlg AS DWORD
                                           SetGetDlg(TempSetDlg, TempGetDlg)
                  MSGBOX FUNCNAME$ + $CR + STR$(TempGetDlg)
                  
                                      END IF
                  
                              END SELECT
                      END SELECT
                  END FUNCTION
                  '------------------------------------------------------------------------------
                  
                  '------------------------------------------------------------------------------
                  '   ** Dialogs **
                  '------------------------------------------------------------------------------
                  FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                      LOCAL lRslt AS LONG
                      LOCAL hDlg  AS DWORD
                       LOCAL TemphDlg AS DWORD
                       
                      DIALOG NEW hParent, "Dialog1", 70, 70, 201, 121, %WS_POPUP OR %WS_BORDER _
                          OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
                          %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
                          %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                          %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
                          %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                  
                  
                  '*** Works
                      SetGetDlg(hDlg, TemphDlg)
                  
                  
                  '*** Works but only because I know the Windows Handle
                      LOCAL retvar AS DWORD
                  
                      DIALOG SET USER hDlg, 1, hDlg
                      DIALOG GET USER hDlg, 1 TO retvar
                  MSGBOX FUNCNAME$ + $CR + STR$(retvar)
                  
                  
                  '*** Doesn't work ???? because I need the Handle to get the handle?
                      DIALOG SET USER %IDD_DIALOG1, 1, hDlg
                      DIALOG GET USER %IDD_DIALOG1, 1 TO retvar
                  MSGBOX FUNCNAME$ + $CR + STR$(retvar)
                  
                  
                  
                      CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Button1", 5, 5, 45, 20
                      DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                      FUNCTION = lRslt
                  END FUNCTION
                  '------------------------------------------------------------------------------
                  
                  
                  FUNCTION SetGetDlg(BYREF SetHwndDlg AS DWORD, BYREF GetHwndDlg AS DWORD)AS DWORD
                       ON ERROR GOTO ErrHandler
                       STATIC TempHwndDlg AS DWORD
                       IF SetHwndDlg <> 0 THEN
                            GetHwndDlg = SetHwndDlg
                            TempHwndDlg = SetHwndDlg
                       ELSE
                            GetHwndDlg = TempHwndDlg
                       END IF
                       FUNCTION = %False             'Return %False if no errors   '<--- Not really needed but kept for readability
                       EXIT FUNCTION                 'Exit function so correct value returned
                  ErrHandler:                        'If error then jump to here
                       FUNCTION = GetLastError()     'If error then return ErrorNumber
                  END FUNCTION
                  
                  Engineer's Motto: If it aint broke take it apart and fix it

                  "If at 1st you don't succeed... call it version 1.0"

                  "Half of Programming is coding"....."The other 90% is DEBUGGING"

                  "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                  Comment


                  • #10
                    GetDlgItem(hParent,CtrlID) will return the hWnd. The complement to this function seems to be GetDlgCtrlID(hWnd), which, if you know the hWnd, will return the CtrlID.
                    At first glance, they would seem to be complements but that is only true in a single container(parent) environment.
                    Because a function like EnumChildWindows returns the handles of all the descendants of a container, you cannot use
                    GetDlgCtrlID to definitively determine that the control id it produces belongs to a control you created. Don't forget
                    that controls embedded in complex controls can have the save identifiers as controls you created. This is something
                    you have no control over.
                    Dominic Mitchell
                    Phoenix Visual Designer
                    http://www.phnxthunder.com

                    Comment


                    • #11
                      I have not dug into this too closely, but from what I have read here this is more an exercise in "using variables" and "managing my program's data" than in "doing cool stuff with Windows' Enumxxxx functions."

                      DIALOG NEW returns "hDlg". Save it in a variable just like you'd save any other variable you need.

                      Or, if you need it in a support function which is called from the dialog procedure for a window, pass CBHNDL as a parameter to that function

                      Or, if you have two dialogs which need to be aware of each other and they do not have a parent-child relationship...

                      Code:
                       DIALOG NEW   ...  to hDlg1
                         CONTROL ADD....
                       DIALOG NEW       to hDlg2 
                         CONTROL ADD 
                      
                       DIALOG SET USER hDlg1, 1, hDlg2
                       DIALOG SET USER hdlg2, 1, hDlg1 
                       DIALOG SHOW MODELESS hDlg1 CALL dlgProc1
                       DIALOG SHOW MODELESS hDlg2 CALL dlgProc2
                       DDT Message loop here
                      If you have to, use DIALOG SHOW STATE hdlgx , %SW_HIDE to prevent a particular screen from showing until needed.

                      In either DlgProc, you can always get a handle to the companion screen with
                      Code:
                           DIALOG GET USER CBHNDL, 1 TO hDlgCompanion
                      I must be missing something here, since this is just too obvious.

                      MCM
                      Last edited by Michael Mattias; 16 Dec 2007, 09:51 AM.
                      Michael Mattias
                      Tal Systems Inc. (retired)
                      Racine WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        I honestly hadn't thought of that Dominic, but I see your point. Frequently I write my own grids, and when I do I always use ordinary buttons for the header row at the top (one for each column, of course), and I always also use buttons for the left side of the grid so that the user can click on a button to highlight a row for whatever application specific task might be required. Inside the custom control during its WM_CREATE message the grid builds itself and I just use an incrementing counter variable for the control ID parameter in the CreateWindow() calls for all these buttons. And since a grid can have virtually any number of rows or columns, there is no way of telling which range of numbers have been used up for control IDs.

                        Now of course the plot thickens if you put one of these grids (or two of these grids, or three of these grids....) on a form/dialog, then for good measure add another button or two or three to the form/dialog not associated or part of the grid, i.e., a button that does something else.

                        I can see where in that case a call to GetDlgItem(hParent,%CTRL_ID) will probably succeed and return when it encounters the first control (which may not be the one you want) with a ctrl id of %CTRL_ID. But if you go to the trouble of setting up the callback for EnumChildWindows, how will that function solve your troubles, as you are still going to end up with a list of hWnds, multiple ones of which still have the same Ctrl ID? I'm assumming one would have to do further checks testing for the parent and so on?

                        In any case, in Cliff's case he was only asking about less complex cases than this, and I believe he'd be will served by GetDlgItem(). There are certainly many cases (in fact I'd go so far as to say the vast majority) where this simple function will give successful results, and it clearly will in the case Cliff presented. I don't follow DDT code very well at all, but I'm assumming most Api functions work in that context.

                        Just to prove my point (and I fully understand yours now), below is a very simple app that has a 2 labels, three textboxes, and two buttons. One enters a length and a width in two of the textboxes, and the Area shows up in a third. The one button is for calculating the area and the other button is for clearing the form/dialog so that one can do another calculation. The only even slightly interesting thing about this app (which I'm sure isn't all that interesting to a coder such as yourself) is that all the controls are subclassed to allow entry to proceed without use of the mouse to reset focus. The program cycles through all the child window controls just by using the [ENTER] key.

                        Now, not only doesn't this app have any global hWnds it doesnt have any local ones either, other than for one Local hWnd for the CreateWindowEx() call in WinMain() to create the main program window. What I had to do to accomplish this is truely ugly (you'll laugh or be appalled when you see it), but all I wanted to do was prove a point. Here's the program...

                        Code:
                        #Compile Exe
                        #Include "Win32api.inc"
                        %IDC_LABEL1   =   1500
                        %IDC_LABEL2   =   1505
                        %IDC_TEXT1    =   1510
                        %IDC_TEXT2    =   1515
                        %IDC_TEXT3    =   1520
                        %IDC_BUTTON1  =   1525
                        %IDC_BUTTON2  =   1530
                        
                        Global fnOldEditProc    As Long
                        Global fnOldButtonProc  As Long
                        
                        Type WndEventArgs
                          wParam                As Long          'Package parameters to Window Procedure in TYPE
                          lParam                As Long
                          hWnd                  As Dword
                          hInst                 As Dword
                        End Type
                        
                        
                        Function fnNewEditProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                          If wMsg=%WM_CHAR Then
                             Select Case Lowrd(wParam)
                               Case 8      'backspace
                                 'backspace is OK
                               Case 13     'backspace or enter key
                                 Select Case GetDlgCtrlID(hWnd)
                                   Case %IDC_TEXT1
                                     Call SetFocus(GetDlgItem(GetParent(hWnd),%IDC_TEXT2))
                                   Case %IDC_TEXT2
                                     Call SetFocus(GetDlgItem(GetParent(hWnd),%IDC_BUTTON1))
                                   Case %IDC_TEXT3
                                     Call SetFocus(GetDlgItem(GetParent(hWnd),%IDC_BUTTON2))
                                 End Select
                               Case 46
                                  'Decimal Point
                               Case 48 To 57
                                 'A number key was pressed
                               Case Else      'If any other key is pressed other than one of those listed above,
                                 wParam=0     'it will be contained in wParam and it will be collected here in
                             End Select       'the 'Else' clause.  Here it will be 'eaten' rather than passed on
                          End If              'to the original text box window procedure in User32.dll.  Therefore,
                                              'it won't show up in the text box
                          fnNewEditProc=CallWindowProc(fnOldEditProc,hWnd,wMsg,wParam,lParam)
                        End Function
                        
                        
                        Function fnNewButtonProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                          If wMsg=%WM_CHAR And wParam=13 And GetDlgCtrlID(hWnd) = %IDC_BUTTON1 Then
                             SendMessage(GetParent(hWnd),%WM_COMMAND,MakDwd(%IDC_BUTTON1,%BN_CLICKED),GetDlgItem(hWnd,%IDC_BUTTON1))
                          End If
                          If wMsg=%WM_CHAR And wParam=13 And GetDlgCtrlID(hWnd) = %IDC_BUTTON2 Then
                             SendMessage(GetParent(hWnd),%WM_COMMAND,MakDwd(%IDC_BUTTON2,%BN_CLICKED),GetDlgItem(hWnd,%IDC_BUTTON2))
                          End If
                        
                          fnNewButtonProc=CallWindowProc(fnOldButtonProc,hWnd,wMsg,wParam,lParam)
                        End Function
                        
                        
                        Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
                          Local lpCreateStruct As CREATESTRUCT Ptr
                        
                          lpCreateStruct=Wea.lParam   'Can use GetModuleHandle() here instead
                          [email protected]
                          CreateWindowEx 0,"static","Length",%WS_CHILD Or %WS_VISIBLE,10,10,80,25,Wea.hWnd,%IDC_LABEL1,Wea.hInst,Byval 0
                          fnOldEditProc= _
                          SetWindowLong _
                          ( _
                            CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,10,80,25,Wea.hWnd,%IDC_TEXT1,Wea.hInst,Byval 0), _
                            %GWL_WNDPROC, _
                            CodePtr(fnNewEditProc) _
                          )
                          CreateWindowEx 0,"static","Width",%WS_CHILD Or %WS_VISIBLE,10,60,80,25,Wea.hWnd,%IDC_LABEL2,Wea.hInst,Byval 0
                          fnOldEditProc= _
                          SetWindowLong _
                          ( _
                            CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,60,80,25,Wea.hWnd,%IDC_TEXT2,Wea.hInst,Byval 0), _
                            %GWL_WNDPROC, _
                            CodePtr(fnNewEditProc) _
                          )
                          fnOldButtonProc= _
                          SetWindowLong _
                          ( _
                            CreateWindowEx(0,"Button","Calculate",%WS_CHILD Or %WS_VISIBLE,80,120,150,25,Wea.hWnd,%IDC_BUTTON1,Wea.hInst,Byval 0), _
                            %GWL_WNDPROC, _
                            CodePtr(fnNewButtonProc) _
                          )
                          CreateWindowEx %WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,80,180,150,25,Wea.hWnd,%IDC_TEXT3,Wea.hInst,Byval 0
                          fnOldButtonProc= _
                          SetWindowLong _
                          ( _
                            CreateWindowEx(0,"Button","Clear",%WS_CHILD Or %WS_VISIBLE,125,225,60,25,Wea.hWnd,%IDC_BUTTON2,Wea.hInst,Byval 0), _
                            %GWL_WNDPROC, _
                            CodePtr(fnNewButtonProc) _
                          )
                          SetFocus(GetDlgItem(wea.hWnd,%IDC_TEXT1))
                        
                          fnWndProc_OnCreate=0
                        End Function
                                         
                        
                        Sub cmdCalculate_Click(Wea As WndEventArgs)
                          Local dblLength, dblWidth, dblArea As Double
                          Local szBuffer As Asciiz*64
                        
                          GetWindowText(GetDlgItem(Wea.hWnd,%IDC_TEXT1),szBuffer,64)
                          dblLength=Val(szBuffer)
                          GetWindowText(GetDlgItem(Wea.hWnd,%IDC_TEXT2),szBuffer,64)
                          dblWidth=Val(szBuffer)
                          szBuffer="Area = " & Format$(dblLength*dblWidth,"######0.00")
                          SetWindowText(GetDlgItem(Wea.hWnd,%IDC_TEXT3),szBuffer)
                          SetFocus(GetDlgItem(Wea.hWnd,%IDC_BUTTON2))
                        End Sub
                        
                        
                        Sub cmdClear_Click(Wea As WndEventArgs)
                          Local hEdit As Dword  'Only used locally to avoid bad practice of calling same function
                                                                   multiple times for same information.
                          hEdit=GetDlgItem(Wea.hWnd,%IDC_TEXT1)
                          SetWindowText(hEdit,"")
                          SetFocus(hEdit)
                          hEdit=GetDlgItem(Wea.hWnd,%IDC_TEXT2)
                          SetWindowText(hEdit,"")
                          hEdit=GetDlgItem(Wea.hWnd,%IDC_TEXT3)
                          SetWindowText(hEdit,"")
                        End Sub
                        
                        
                        Function fnWndProc_OnCommand(Wea As WndEventArgs) As Long
                          Select Case As Long Lowrd(wea.wParam)
                            Case %IDC_BUTTON1
                              If Hiwrd(Wea.wParam)=%BN_CLICKED Then
                                 Call cmdCalculate_Click(Wea)
                              End If
                            Case %IDC_BUTTON2
                              If Hiwrd(Wea.wParam)=%BN_CLICKED Then
                                 Call cmdClear_Click(Wea)
                              End If
                          End Select
                        
                          fnWndProc_OnCommand=0
                        End Function
                        
                        
                        Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
                          Call PostQuitMessage(0)
                          fnWndProc_OnDestroy=0
                        End Function
                        
                        
                        Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                          Local Wea As WndEventArgs
                        
                          Select Case As Long wMsg
                            Case %WM_CREATE
                              Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                              fnWndProc=fnWndProc_OnCreate(Wea)
                              Exit Function
                            Case %WM_COMMAND
                              Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                              fnWndProc=fnWndProc_OnCommand(Wea)
                              Exit Function
                            Case %WM_DESTROY
                              Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                              fnWndProc=fnWndProc_OnDestroy(Wea)
                              Exit Function
                          End Select
                        
                          fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
                        End Function
                        
                        
                        Function WinMain(ByVal hIns As Long,ByVal hPrev As Long,ByVal lpCL As Asciiz Ptr,ByVal iShow As Long) As Long
                          Local winclass As WndClassEx
                          Local szAppName As Asciiz*16
                          Local Msg As tagMsg
                          Local hWnd As Dword
                        
                          szAppName="Basic Stuff"
                          winclass.cbSize=SizeOf(winclass)
                          winclass.style=%CS_HREDRAW Or %CS_VREDRAW
                          winclass.lpfnWndProc=CodePtr(fnWndProc)
                          winclass.cbClsExtra=0
                          winclass.cbWndExtra=0
                          winclass.hInstance=hIns
                          winclass.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
                          winclass.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)
                          winclass.hbrBackground=%COLOR_BTNFACE+1
                          winclass.lpszMenuName=%NULL
                          winclass.lpszClassName=VarPtr(szAppName)
                          Call RegisterClassEx(winclass)
                          hWnd=CreateWindow(szAppName,"Basic Form",%WS_OVERLAPPEDWINDOW,200,100,325,300,0,0,hIns,ByVal 0)
                          Call ShowWindow(hWnd,iShow)
                          While GetMessage(Msg,%NULL,0,0)
                            Call TranslateMessage(Msg)
                            Call DispatchMessage(Msg)
                          Wend
                        
                          Function=msg.wParam
                        End Function
                        Fred
                        "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                        Comment


                        • #13
                          This is turning into a "Proof of Concept" idea.
                          Sure I could just easily have a Global Variable to hold the Handle to a Dialog, or pass the CBHNDL from my callback to a function.
                          In these 2 cases I know what the Handle is. But lets say I have a function that is not passed the Handle, that I could still get the Handle from a local variable.

                          With my above code, it seems to work. Although I have to expand on it.
                          Hopefully shortly I will have a full working source for the idea.
                          Engineer's Motto: If it aint broke take it apart and fix it

                          "If at 1st you don't succeed... call it version 1.0"

                          "Half of Programming is coding"....."The other 90% is DEBUGGING"

                          "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                          Comment


                          • #14
                            But if you go to the trouble of setting up the callback for EnumChildWindows, how will that
                            function solve your troubles, as you are still going to end up with a list of hWnds, multiple
                            ones of which still have the same Ctrl ID? I'm assumming one would have to do further checks
                            testing for the parent and so on?
                            In a constrained environment, I use the GetParent check.
                            For example, given a form with the following two controls:
                            Code:
                            Control              | Identifier               |   Background Color
                            ---------------------|--------------------------|-------------------
                            ListBox              | 1000(IDC_FORM1_LIST1)    |   Magenta
                            ComboBox(CBS_SIMPLE) | 102 (IDC_FORM1_COMBO1)   |   White(default)
                            The following code produces the wrong result because both controls are painted magenta.
                            Code:
                             
                                CASE %WM_CTLCOLORLISTBOX                                             
                                  IF GetDlgCtrlID(lParam) = %IDC_FORM1_LIST1 THEN
                                    ' Return handle of brush used to paint background
                                    FUNCTION = GetProp(GetDlgItem(hWnd, %IDC_FORM1_LIST1), "BRUSH")
                                    EXIT FUNCTION
                                  END IF
                            This code produces the correct result. Only the listbox is painted magenta.
                            Code:
                             
                                CASE %WM_CTLCOLORLISTBOX                                             
                                  IF GetParent(lParam) = hWnd THEN
                                    IF GetDlgCtrlID(lParam) = %IDC_FORM1_LIST1 THEN
                                      ' Return handle of brush used to paint background
                                      FUNCTION = GetProp(GetDlgItem(hWnd, %IDC_FORM1_LIST1), "BRUSH")
                                      EXIT FUNCTION
                                    END IF  
                                  END IF
                            The first code fails because the embedded ComboLBox of the ComboBox(CBS_SIMPLE) has an
                            identifier of 1000. Both the listbox and combobox send the WM_CTLCOLORLISTBOX message
                            to the parent window.

                            I will also use the GetParent check during enumeration iff the enironment is constrained.
                            The Layout Manager in Phoenix is an example of this where only certain types of parent
                            containers are allowed.

                            When I write custom controls that need to find each other via enumeration, I give each
                            control class a unique ID that is assigned to each instance of the control. The docking
                            and ActiveX containers in Phoenix depend heavily on this technique.

                            For example.
                            Code:
                                 
                            $ID_TENANT        = "{78A356F1-5E32-4195-846E-7A5F872995B9}"
                            
                            '----------------------------------------------------------------------
                            
                            FUNCTION OnCreate(BYVAL hWnd AS DWORD, BYVAL lParam AS LONG) AS LONG
                            
                              LOCAL ptocd           AS OLECONTAINERDATA PTR
                              LOCAL ptcs            AS CREATESTRUCT PTR
                              LOCAL pthd            AS HOOKDATA PTR
                              LOCAL dwThreadID      AS DWORD
                              LOCAL lpfnOldWndProc  AS DWORD
                              LOCAL pContainer      AS DWORD
                              LOCAL hr              AS LONG
                            
                              ptcs = lParam
                            
                              ' Make sure the OLE library is loaded
                              OleInitialize BYVAL %NULL
                            
                              ptocd = HeapAlloc(GetProcessHeap(), %HEAP_ZERO_MEMORY, SIZEOF(@ptocd))
                              IF ISFALSE ptocd THEN
                                FUNCTION = -1
                                EXIT FUNCTION
                              END IF
                              SetWindowLong hWnd, 0, ptocd
                            
                              ' Control identifier
                              SetProp hWnd, $ID_TENANT, &H584E4850???     ' PHNX
                            
                              ...
                              
                            END FUNCTION
                              
                            '----------------------------------------------------------------------
                            '
                            ' FUNCTION: OleContainerEnumProc
                            ' PURPOSE:  Enumerates all OLE containers on the immediate parent
                            '           window.
                            '
                            '----------------------------------------------------------------------
                            
                            FUNCTION OleContainerEnumProc _
                              ( _
                              BYVAL hWnd    AS DWORD, _ ' handle of child window
                              BYVAL lParam  AS LONG _   ' address of enumeration data
                              ) AS LONG
                            
                              LOCAL plRet AS LONG PTR
                            
                              plRet = lParam
                            
                              IF ISTRUE GetProp(hWnd, $ID_TENANT) THEN
                                @plRet = %TRUE
                                FUNCTION = %FALSE
                                EXIT FUNCTION
                              END IF
                            
                              FUNCTION = %TRUE
                            
                            END FUNCTION
                            
                            '----------------------------------------------------------------------
                            '
                            ' FUNCTION: HasOleContainer
                            ' PURPOSE:  Returns True if an OLE container is present on a form.
                            '
                            '----------------------------------------------------------------------
                            
                            FUNCTION HasOleContainer _
                              ( _
                              BYVAL hWnd  AS DWORD _  ' handle of top-level window
                              ) AS LONG
                            
                              LOCAL lRet  AS LONG
                            
                              EnumChildWindows hWnd, CODEPTR(OleContainerEnumProc), VARPTR(lRet)
                            
                              FUNCTION = lRet
                            
                            END FUNCTION

                            As for Cliff, he asked this
                            Is there a way to find the "Windows Handle" of a Dialog or Window that I created in one function
                            so that it can be used in other functions? Without declaring my variable as global?....or IE:
                            I know the Equates value for the Window, but if I need to get the Windows Handle outside the function
                            it was created in, is there a way?
                            This is very easy to accomplish. Either I don't understand what he asking, or he thinks this problem
                            is a lot more difficult than it really is.
                            Dominic Mitchell
                            Phoenix Visual Designer
                            http://www.phnxthunder.com

                            Comment


                            • #15
                              ow, not only doesn't this app have any global hWnds it doesnt have any local ones either,
                              other than for one Local hWnd for the CreateWindowEx() call in WinMain() to create the main
                              program window. What I had to do to accomplish this is truely ugly (you'll laugh or be appalled
                              when you see it), but all I wanted to do was prove a point. Here's the program...
                              Ugly? It looks pretty normal to me. I use GetDlgItem/GetParent quite a bit.
                              Dominic Mitchell
                              Phoenix Visual Designer
                              http://www.phnxthunder.com

                              Comment


                              • #16
                                conflicting control ids

                                Continuing further with this discussion of possible difficulties one might encounter if controls have conflicting (the same) control id, would it not luckily be true that any bugs caused by this would have to show up at development time, rather than later, for example on a client's machine?

                                For example, say you have a button on your main form/dialog which you have given the id number 10500. Further, lets say you instantiated a common control such as a day-month calendar control (or whatever its called) on the same window with the button and by some chance one of its constituent controls also uses 10500 to identify something in it. It certainly could happen that GetDlgItem(hMainWnd,10500) would come up with the handle to some internal calendar object rather than your button. But it wouldn't be a variable type occurance would it? I mean a situation where one program run it comes up with one control and another run with another? Or one machine with the button control 10500 and another machine with the like numbered object in the calendar?

                                It seems to me if my reasoning is correct that this issue is a minor potential problem for that reason. I expect one would find it out fairly readily during program development, as Dominic's above listed code shows?
                                Fred
                                "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                                Comment


                                • #17
                                  I expect one would find it out fairly readily during program development, as Dominic's above listed code shows?
                                  I would expect one's success detecting this error during development rather than after installation would be directly related to the amount of effort expended and the quality of testing.

                                  MCM
                                  Michael Mattias
                                  Tal Systems Inc. (retired)
                                  Racine WI USA
                                  [email protected]
                                  http://www.talsystems.com

                                  Comment


                                  • #18
                                    I would expect one's success detecting this error during development rather than after installation would be directly related to the amount of effort expended and the quality of testing.
                                    I would expect that this error should manifest itself should one expend that amount of effort required to depress a button on said Dialog/Form, said Dialog/Form being further distinguished by having another control of the same ID as aformentioned button. And here's a DDT program with no Global hWnds if Cliff still needs it...

                                    Code:
                                    #Compile Exe
                                    #Dim All
                                    #Include "Win32Api.inc"
                                    %IDC_BUTTON    =   1250
                                    %IDC_EDIT1     =   1275
                                    %IDC_EDIT2     =   1300
                                    %IDC_EDIT3     =   1325
                                    %IDC_EDIT4     =   1350
                                    
                                    Sub XButton_OnClick()
                                      MsgBox("You Clicked The 'X' Button!")
                                    End Sub
                                    
                                    Callback Function ddtWndProc()
                                      Select Case CBMsg
                                        Case %WM_COMMAND
                                          If CBCtlMsg=%BN_CLICKED And CBCtl=%IDC_BUTTON Then
                                             Local szBuffer As Asciiz*64
                                             Local hParent,hCtrl As Dword
                                             MsgBox("Thanks!  I Needed That!")
                                             hParent=CBHndl
                                             szBuffer="hMainWnd=" & Trim$(Str$(hParent))
                                             Control Set Text CBHndl,%IDC_EDIT2,szBuffer
                                             hCtrl=GetDlgItem(hParent,%IDC_BUTTON)
                                             Control Set Text CBHndl,%IDC_EDIT4,"hButton=" & Trim$(Str$(hCtrl))
                                             Function=%TRUE
                                          End If
                                        Case %WM_SYSCOMMAND
                                          If (CBwParam And &HFFF0)=%SC_CLOSE Then
                                             Call XButton_OnClick()
                                          End If
                                      End Select
                                    End Function
                                    
                                    
                                    Function PBMain() As Long
                                      Local hMainWnd,hCtrl,iRetVal As Long
                                    
                                      Dialog New Pixels,0,"No Stinkin Globals!",100,100,375,200,%WS_OVERLAPPEDWINDOW Xor %WS_MAXIMIZEBOX To hMainWnd
                                      Control Add Button, hMainWnd,%IDC_BUTTON,"I'm A Button.  Click Me!", 60,20,250,25,%BS_DEFAULT or %WS_TABSTOP
                                      Control Add Label, hMainWnd,-1,"HMainWnd From PBMain()",10,70,220,25,%WS_CHILD Or %WS_VISIBLE
                                      Control Add Textbox, hMainWnd,%IDC_EDIT1,"", 235,70,125,25, %WS_CHILD Or %WS_VISIBLE Or %WS_BORDER
                                      hCtrl=GetDlgItem(hMainWnd,%IDC_EDIT1)
                                      SetWindowText(hCtrl,"hMainWnd=" & Trim$(Str$(hMainWnd)))
                                      Control Add Label, hMainWnd,-1,"HMainWnd From ddtWndProc()",10,100,220,25,%WS_CHILD Or %WS_VISIBLE
                                      Control Add Textbox, hMainWnd,%IDC_EDIT2,"", 235,100,125,25, %WS_CHILD Or %WS_VISIBLE Or %WS_BORDER
                                      Control Add Label, hMainWnd,-1,"hButton From PBMain()",10,130,200,25,%WS_CHILD Or %WS_VISIBLE
                                      Control Add Textbox, hMainWnd,%IDC_EDIT3,"", 235,130,125,25, %WS_CHILD Or %WS_VISIBLE Or %WS_BORDER
                                      hCtrl=GetDlgItem(hMainWnd,%IDC_BUTTON)
                                      Control Set Text hMainWnd,%IDC_EDIT3,"hButton=" & Trim$(Str$(hCtrl))
                                      Control Add Label, hMainWnd,-1,"hBtn From ddtWndProc()",10,160,200,25,%WS_CHILD Or %WS_VISIBLE
                                      Control Add Textbox, hMainWnd,%IDC_EDIT4,"", 235,160,125,25, %WS_CHILD Or %WS_VISIBLE Or %WS_BORDER
                                      Dialog Show Modal hMainWnd Call ddtWndProc To iRetVal
                                        
                                      PBMain=0
                                    End Function
                                    Fred
                                    "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                                    Comment


                                    • #19
                                      Thanx Fred, the code is similar to one train of thought that I had.
                                      I have been sitting back and reading how things spun off to some debate (Although fun to watch, amazed how the question could be spun so hard )

                                      Anyways as to my original question, I think the simple answer is, unless you pass the handle to the function/sub that needs it, then you need the handle itself to begin with. (Aka in this case call it Dialog, Window, ParentWindow, VB-Form, whatever)

                                      In all cases (DDT, SDK, PB, API, MyProgLanguageOfChoice, etc...) it boils down to
                                      1. Callback Function (in this case CBHNDL is known and used (or passed to other functions
                                      2. Register a function to process my messages (in this case, lets say FUNCTION Dialog_Proc( _
                                        BYVAL hWnd AS DWORD, _ ' window handle
                                        BYVAL uMsg AS DWORD, _ ' type of message
                                        BYVAL wParam AS DWORD, _ ' first message parameter
                                        BYVAL lParam AS LONG _ ' second message parameter
                                        ) AS LONG
                                        hWnd is passed and used.
                                      3. Get window, and other API functions, can get a handle, but you must pass the Handle to the Dialog/Window/VBForm etc to get some handle (This is where I think I lost everyone, but hey I can lose myself sometimes trying to understand enough to ask the "Right Question"


                                      Thats when I came up with my own solution (or I think I have), that no Global, and still be able to get the Handle I need to pass to perform some operation. (Although probably re-creating the wheel, or some other trick) but lets say I had the below.

                                      Demo Dialog Handle Prob.bas -----> This creates my solution to the problem
                                      Code:
                                      #COMPILE DLL
                                      #DIM ALL
                                      
                                      #INCLUDE "Win32API.inc"
                                      DECLARE FUNCTION LIBMAIN (BYVAL hInstance   AS LONG, _
                                                        BYVAL fwdReason   AS LONG, _
                                                        BYVAL lpvReserved AS LONG) AS LONG
                                      
                                      DECLARE FUNCTION AppMsgPump() AS LONG
                                      DECLARE FUNCTION CreateMyDialog ALIAS "CreateMyDialog"() AS LONG
                                      DECLARE FUNCTION SetGetDlg(BYREF SetHwndDlg AS DWORD, BYREF GetHwndDlg AS DWORD)AS DWORD
                                      DECLARE FUNCTION CallMyDialogHandle ALIAS "CallMyDialogHandle"() AS LONG
                                      
                                      
                                      '-------------------------------------------------------------------------------
                                      ' Main DLL entry point called by Windows...
                                      '
                                      FUNCTION LIBMAIN (BYVAL hInstance   AS LONG, _
                                                        BYVAL fwdReason   AS LONG, _
                                                        BYVAL lpvReserved AS LONG) AS LONG
                                          SELECT CASE fwdReason
                                      
                                               CASE %DLL_PROCESS_ATTACH
                                                   FUNCTION = 1   'success!
                                                   'FUNCTION = 0   'failure!  This will prevent the EXE from running.
                                               CASE %DLL_PROCESS_DETACH
                                                   FUNCTION = 1   'success!
                                                   'FUNCTION = 0   'failure!
                                               CASE %DLL_THREAD_ATTACH
                                                   FUNCTION = 1   'success!
                                                   'FUNCTION = 0   'failure!
                                               CASE %DLL_THREAD_DETACH
                                                   FUNCTION = 1   'success!
                                                   'FUNCTION = 0   'failure!
                                          END SELECT
                                      END FUNCTION
                                      
                                      FUNCTION AppMsgPump() AS LONG
                                           ON ERROR GOTO ErrHandler
                                           LOCAL tmsg AS TagMsg
                                      '*** Acquire and dispatch messages until a WM_QUIT message is received.
                                           WHILE ISTRUE GetMessage(tmsg, BYVAL %NULL, 0, 0)
                                                TranslateMessage tmsg
                                                DispatchMessage tmsg
                                           WEND
                                           FUNCTION = %True    'Function results
                                           EXIT FUNCTION       'Escape function so not to trigger error log
                                      ErrHandler:
                                           'Do some error handling
                                      END FUNCTION
                                      
                                      FUNCTION CreateMyDialog ALIAS "CreateMyDialog"() EXPORT AS LONG
                                          LOCAL hDlg  AS DWORD
                                           LOCAL TemphDlg AS DWORD
                                      
                                          DIALOG NEW %HWND_DESKTOP, "Dialog1", 70, 70, 201, 121, %WS_POPUP OR %WS_BORDER _
                                              OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
                                              %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
                                              %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                                              %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
                                              %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                                      
                                      
                                      '*** Works
                                          SetGetDlg(hDlg, TemphDlg)
                                      
                                      END FUNCTION
                                      
                                      FUNCTION SetGetDlg(BYREF SetHwndDlg AS DWORD, BYREF GetHwndDlg AS DWORD)EXPORT AS DWORD
                                           ON ERROR GOTO ErrHandler
                                           STATIC TempHwndDlg AS DWORD
                                           IF SetHwndDlg <> 0 THEN
                                                GetHwndDlg = SetHwndDlg
                                                TempHwndDlg = SetHwndDlg
                                           ELSE
                                                GetHwndDlg = TempHwndDlg
                                           END IF
                                      MSGBOX "Dll Created Dlg Handle = " + STR$(TempHwndDlg)
                                           FUNCTION = %False             'Return %False if no errors   '<--- Not really needed but kept for readability
                                           EXIT FUNCTION                 'Exit function so correct value returned
                                      ErrHandler:                        'If error then jump to here
                                           FUNCTION = GetLastError()     'If error then return ErrorNumber
                                      END FUNCTION
                                      
                                      FUNCTION CallMyDialogHandle ALIAS "CallMyDialogHandle"() EXPORT AS LONG
                                          LOCAL hDlg  AS DWORD
                                           LOCAL TemphDlg AS DWORD
                                      '*** Works
                                      '    SetGetDlg(hDlg, TemphDlg)
                                          FUNCTION = TemphDlg
                                      END FUNCTION
                                      Test Problems.bas -----> This shows my solution works
                                      Code:
                                      #COMPILE EXE
                                      #DIM ALL
                                      #INCLUDE "Win32Api.inc"
                                      DECLARE FUNCTION CreateMyDialog LIB "Demo Dialog Handle Prob.dll" ALIAS "CreateMyDialog"() AS LONG
                                      DECLARE FUNCTION CallMyDialogHandle LIB "Demo Dialog Handle Prob.dll" ALIAS "CallMyDialogHandle"() AS LONG
                                      
                                      FUNCTION PBMAIN () AS LONG
                                           CreateMyDialog
                                      MSGBOX "Main App Calling returned " + STR$(CallMyDialogHandle)+ " as the Dialog Handle"
                                      END FUNCTION
                                      Its all still in testing, but sure beats the heck out of Losing track of Global variables, or accidentally declaring the same global variable for 2 completely different things
                                      Engineer's Motto: If it aint broke take it apart and fix it

                                      "If at 1st you don't succeed... call it version 1.0"

                                      "Half of Programming is coding"....."The other 90% is DEBUGGING"

                                      "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                                      Comment


                                      • #20
                                        Get window, and other API functions, can get a handle, but you must pass the Handle to the Dialog/Window/VBForm etc to get some handle (This is where I think I lost everyone, but hey I can lose myself sometimes trying to understand enough to ask the "Right Question"
                                        Must, no. Optional, yes.

                                        I could write an app, and be able to obtain the handle of any window in that app from any function(within the same app or another process) without needing to know the handle of any window in that app.
                                        Dominic Mitchell
                                        Phoenix Visual Designer
                                        http://www.phnxthunder.com

                                        Comment

                                        Working...
                                        X