Announcement

Collapse
No announcement yet.

CONTROL ADD "Custom" Not Working

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

  • Cecil Williams
    Guest replied
    Mark,

    Great to hear. I would add WM_NOTIFY to your parent window's
    procedure that the conrol belongs to. You might be surprised
    at the messages you're missing. Most custom controls pass a
    lot of notifications for the parent to either process or force
    the control to process.

    Just thought of another possible way to get the control class
    name. Make a call to the ControlCreate() function. Pass the
    handle to the API GetClassName() function. See below. This could
    get the data you're looking for.

    Code:
    int GetClassName(
      HWND hWnd,           // handle of window
      LPTSTR lpClassName,  // address of buffer for class name
      int nMaxCount        // size of buffer, in characters
    );
    Good luck with the control!!!!!!!!

    Cheers,
    Cecil

    ------------------

    Leave a comment:


  • Mark Newman
    replied
    An update - using the MS "Spy++" utility on the sample compiled C program I was able to
    find the class name. I plugged that into the CONTROL ADD statement and Poof! DDT is now
    creating a control window. So my window handles are:

    Main dialog hWnd = 5506054
    DLL Control hwnd = 1311912

    which seem valid enough. The control window is now visible though the positioning
    is off and the control contents are blank. Who cares! It's showing!!!

    When I started this porting project, I never thought getting the 3 lines of code that show
    the window would be so hard; I figured that some of the other functions that use double-
    indirection (**var) would be the tough ones. Maybe they'll be easy in comparison! In any
    case, thanks for all the help; there's only 1 line of code left!

    ------------------
    Mark Newman

    [This message has been edited by Mark Newman (edited March 22, 2001).]

    Leave a comment:


  • Peter Scheutz
    replied
    Originally posted by Mark Newman:
    Hi all,
    Troubles with CONTROL ADD "Custom".
    But when I create the control using:
    Code:
       Control Add "MyControl", hDlg, %MYCONTROL, "Title", 1,50,300,150, %WS_VISIBLE Or %WS_TABSTOP Or %WS_CHILD, 0&
    no hWnd to the control is created: CONTROL HANDLE returns 0. In addition, ERR is 0 after the CONTROL ADD call.
    Please excuse this shot in the dark, but I seem to recall fixing something similar, by using a class name of max 8 characters.
    That would be "MyControl" -> "MControl"

    --
    Best Regards
    Peter Scheutz


    ------------------

    Leave a comment:


  • Semen Matusovski
    replied
    I don't see any problems with custom contols in DLL. (at least, under Win2000)
    Borje's code after small modification
    1) DLL
    Code:
       #Compile Dll "PbDll.Dll"
       #Dim All
       #Register None
       #Include "Win32Api.Inc"
       
       Function frmMain_DLGPROC(ByVal hWnd As Long, ByVal wMsg As Long, _
                                ByVal wParam As Long, ByVal lParam As Long) As Long
    
       Local ps As PAINTSTRUCT, r As RECT, zText As Asciiz * 255
       Select Case wMsg
          Case %WM_LBUTTONDOWN : MsgBox "Oh"  '<- just to see it works
          Case %WM_PAINT
             If GetWindowText(hWnd, zText, SizeOf(zText)) Then  '<- if control has any text
                BeginPaint hWnd, ps                             '<- start paint procedure
                GetClientRect hWnd, r                         '<- get coordinates
                SetBkMode ps.hDC, %TRANSPARENT                '<- set text mode
                DrawText ps.hDC, zText, -1, r, %DT_SINGLELINE Or %DT_CENTER Or %DT_VCENTER
                EndPaint hWnd, ps                               '<- end paint procedure
             End If
       End Select
       Function = DefWindowProc(hWnd, wMsg, wParam, lParam)
       End Function
    
       Function LibMain(ByVal hInstance As Long, ByVal Reason As Long, ByVal Reserved  As Long) Export As Long
          Select Case Reason
             Case %DLL_PROCESS_ATTACH
                Dim szName As Asciiz * 20, wc As WNDCLASSEX
                szName               = "MyControl"
                wc.cbSize            = SizeOf(wc)
                wc.style             = %CS_HREDRAW Or %CS_VREDRAW Or %CS_PARENTDC Or %CS_GLOBALCLASS
                wc.lpfnWndProc       = CodePtr(frmMain_DLGPROC)
                wc.cbClsExtra        = 0
           wc.cbWndExtra        = 0
           wc.hInstance         = hInstance
           wc.hIcon             = %NULL
           wc.hCursor           = LoadCursor(%NULL, ByVal %IDC_ARROW )
           wc.hbrBackground     = GetStockObject(%NULL_BRUSH)
           wc.lpszMenuName      = %NULL
           wc.lpszClassName     = VarPtr(szName)
           wc.hIconSm           = %NULL
           RegisterClassEx wc
    
      '  Case %DLL_PROCESS_DETACH
       End Select
      LibMain = 1
    End Function
    Exe
    Code:
       #Compile Exe
       #Dim All
       #Register None
       %MYCONTROL = 20
       #Include "WIN32API.INC"
    
       Function PbMain
          Dim hDlg As Long, hwndControl As Long
          LoadLibrary ("PbDll.Dll")
          Dialog New 0, "Custom control test",,, 240, 180, %WS_CAPTION Or %WS_SYSMENU, 0 To hDlg
          Control Add "MyControl", hDlg, %MYCONTROL, "Click here", 4, 20, 228, 142, _
                     %WS_VISIBLE Or %WS_TABSTOP Or %WS_CHILD, %WS_EX_CLIENTEDGE
          Dialog Show Modal hDlg
      End Function

    ------------------
    E-MAIL: [email protected]

    Leave a comment:


  • Mark Newman
    replied
    No word yet from the DLL vendor as to the class name, so I'll have to try and find a
    "snooper" app. Cecil, you're probably right in that the DLL has the RegisterClassEx()
    call somewhere in one of the initialization functions. Just have to find it! BTW, the
    DLL sends very few messages, just a couple of mouse click events. Likewise, I only need
    to inform the control of basic events, such as WM_PAINT; it handles all the painting
    chores.

    Borje, the code you posted is very similar to what I'm doing, so it should work, eh?
    I need to the get the class name of the control, so CONTROL ADD can create a child window
    for the control to paint in. So close and yet so far!

    Thanks!



    ------------------
    Mark Newman

    Leave a comment:


  • Borje Hagsten
    replied
    Okay, I mis-understood and thought it was your DLL. Using CONTROL ADD
    for any kind of custom control class is no problem. Added a piece
    of test code you can play around with and see that it works. The
    control in your DLL probably only needs a handle of the created control,
    so it knows where to perform its painting stuff.

    What you need, is probably the header file in the form of an .INC file,
    where ControlCreate() and ControlAttachWindow is declared. Or, the DLL
    functions declared directly in your program.
    Code:
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Template
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    #COMPILE EXE
    %MYCONTROL = 20
    #INCLUDE "WIN32API.INC"
     
    '#INCLUDE "MYCONTROL.INC" '<- This one for the DLL!!!
    ' ..or declared directly, like:
    ' (Note, I have no idea what they look like - this just sample!)
    ' DECLARE FUNCTION ControlCreate LIB "MYCONTROL.DLL" ALIAS _
                      "ControlCreate" () AS LONG
    ' DECLARE FUNCTION ControlAttachWindow LIB "MYCONTROL.DLL" ALIAS _
                      "ControlAttachWindow" (BYVAL hControlData AS LONG, BYVAL hwndControl AS LONG) AS LONG
     
    DECLARE CALLBACK FUNCTION DlgProc() AS LONG
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Create dialog and controls, etc
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION PBMAIN () AS LONG
      LOCAL hDlg AS LONG, hwndControl AS LONG, lSuccess AS LONG
      LOCAL szName AS ASCIIZ * 20, wc AS WNDCLASSEX
     
      DIALOG NEW 0, "Custom control test",,, 240, 180, %WS_SYSMENU, 0 TO hDlg
      CONTROL ADD BUTTON, hDlg, %IDOK, "&Ok", 180, 4, 50, 14, %WS_BORDER
     
      szName               = "MyControl"
      wc.cbSize            = SIZEOF(wc)
      wc.style             = %CS_HREDRAW OR %CS_VREDRAW OR %CS_PARENTDC OR %CS_GLOBALCLASS
      wc.lpfnWndProc       = CODEPTR(frmMain_DLGPROC)
      wc.cbClsExtra        = 0
      wc.cbWndExtra        = 0
      wc.hInstance         = GetModuleHandle (BYVAL 0)
      wc.hIcon             = %NULL
      wc.hCursor           = LoadCursor(%NULL, BYVAL %IDC_ARROW )
      wc.hbrBackground     = GetStockObject(%NULL_BRUSH)
      wc.lpszMenuName      = %NULL
      wc.lpszClassName     = VARPTR(szName)
      wc.hIconSm           = %NULL
      lSuccess = RegisterClassEx(wc)
     
      CONTROL ADD "MyControl", hDlg, %MYCONTROL, "Click here", 4, 20, 228, 142, _
                  %WS_VISIBLE OR %WS_TABSTOP OR %WS_CHILD, %WS_EX_CLIENTEDGE
     
      hwndControl = GetDlgItem(hDlg, %MYCONTROL)
    '  hControlData = ControlCreate()                 'DLL call: Creates the control and returns a handle to the control's data
    '  CALL ControlAttachWindow(hControlData, hwndControl) 'DLL call: Attaches the control to the control's window handle
     
      DIALOG SHOW MODAL hDlg CALL DlgProc
     
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main callback
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    CALLBACK FUNCTION DlgProc() AS LONG
      SELECT CASE CBMSG
         CASE %WM_COMMAND
            IF CBCTLMSG = %BN_CLICKED THEN
               IF CBCTL = %IDOK THEN DIALOG END CBHNDL
            END IF
      END SELECT
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Custom control procedure
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION frmMain_DLGPROC(BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                             BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
     
      LOCAL ps AS PAINTSTRUCT, r AS RECT, zText AS ASCIIZ * 255
     
      SELECT CASE wMsg
         CASE %WM_LBUTTONDOWN : BEEP     '<- just to see it works
     
         CASE %WM_PAINT
          IF GetWindowText(hWnd, zText, SIZEOF(zText)) THEN  '<- if control has any text
             BeginPaint hWnd, ps                             '<- start paint procedure
               GetClientRect hWnd, r                         '<- get coordinates
               SetBkMode ps.hDC, %TRANSPARENT                '<- set text mode
               DrawText ps.hDC, zText, -1, r, %DT_SINGLELINE OR %DT_CENTER OR %DT_VCENTER
             EndPaint hWnd, ps                               '<- end paint procedure
             FUNCTION = 0 : EXIT FUNCTION                    '<- bail out..
          end if
     
      END SELECT
      FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
    END FUNCTION
    ------------------


    [This message has been edited by Borje Hagsten (edited March 21, 2001).]

    Leave a comment:


  • Cecil Williams
    Guest replied
    Mark,

    Now you're cooking with gas!!! A window creation MUST have a class
    associated with it. Defines all the necessary stuff including
    the window procedure that a window needs to function properly.
    My guess, it's all in the dll.

    Now for the good stuff, what notifications does the control send
    to it's parent and what does it process internally????? This
    should be listed in the docs or header file somewhere. You'll
    need this info to comm corectly with the control.

    Cheers,
    Cecil

    ------------------

    Leave a comment:


  • Mark Newman
    replied
    Hi Cecil,

    No mention of "MYCONTROLCLASS" in the C header files. If I understand things
    correctly, there must be one defined in order for it to be "on-screen". Hmmm.
    Maybe I'll run one of the compiled C examples and look for the class name with
    a "snooper"-type app. I think SysInternals has one?? I'll ask the vendor of
    this control too, though I haven't had the best of luck with them so far.



    ------------------
    Mark Newman

    Leave a comment:


  • Cecil Williams
    Guest replied
    Mark,

    I think you misunderstood me. No mention of Active-X, yuuuk!
    Most custom controls register the class data the way you did.
    Point, does your classname match the dll classname. This would
    be normally listed in the C header file as a constant, ie;

    #define MYCONTROLCLASS "XXXXWhatever"

    If the dll does the registration, which I suspect, all you need
    to do is list it in the CreateWindow function or whatever DDT
    uses.

    If you would like, email me the C header file:

    [email protected]

    I will take a look at it!!!!!

    Cheers,
    Cecil

    ------------------

    Leave a comment:


  • Mark Newman
    replied
    Cecil,

    My port of the C header files is as complete as I can make it, though who knows how correct
    it is. The 3 or 4 functions I'm using just to get the control on the screen are pretty
    straightforward, so I think the DECLARES are ok.

    The DLL I'm using is primarily meant to be distributed with the application, so it isn't
    compiled statically.

    There isn't any ActiveX-type registration or class name since I'm using a DLL. That's why I
    created a class using the RegisterClassEx function in the hope that DDT would see the class
    and create the control. But perhaps DDT was not meant for DLL-type controls? Yet Borje Hagsten
    was able to create his ultra-cool 3D progress bars in straight PB code and create them using
    CONTROL ADD <custom>, so I figure there must be a way.



    ------------------
    Mark Newman

    Leave a comment:


  • Cecil Williams
    Guest replied
    Mark,

    Does your include file register all the constants and function
    declares that are listed in the C header file?

    The C code version does not use "loadlibrary" since the compiled
    exe uses a *.lib for linking at loadtime, not runtime. This the
    way C/C++ links normally.

    Most custom controls have a registration function to register
    all the class data required. Does this one????

    Does "MyControl" match the control's class name?????????

    Just a few things to ponder!!!

    Cheers,
    Cecil

    ------------------

    Leave a comment:


  • Mark Newman
    replied
    Are the DLL's LibMain and WinMain (frmMain_DLGPROC ?) exported,
    that is - do they end with EXPORT AS LONG ?
    I don't have access to the DLL source, but if I run DEPENDS on the DLL I don't see them
    in the list of exported functions. (frmMain_DLGPROC is my PB callback function.)
    Is this a problem?

    Forgot - maybe you need to load the DLL before it can be used,
    with something like:

    lRes = LoadLibrary("MYDLL.DLL")
    IF lRes THEN
    CONTROL ADD.. 'etc.
    ELSE
    EXIT FUNCTION
    END IF
    Hmmm, didn't consider that, though the C sample code I'm using as a
    reference doesn't call LoadLibrary. I'll give it a try.

    Thanks!



    ------------------
    Mark Newman

    Leave a comment:


  • Borje Hagsten
    replied
    Are the DLL's LibMain and WinMain (frmMain_DLGPROC ?) exported,
    that is - do they end with EXPORT AS LONG ?

    Forgot - maybe you need to load the DLL before it can be used,
    with something like:
    Code:
    lRes = LoadLibrary("MYDLL.DLL")
    IF lRes THEN
      CONTROL ADD..  'etc.
    ELSE
      EXIT FUNCTION
    END IF
    ------------------



    [This message has been edited by Borje Hagsten (edited March 21, 2001).]

    Leave a comment:


  • Mark Newman
    started a topic CONTROL ADD "Custom" Not Working

    CONTROL ADD "Custom" Not Working

    Hi all,

    Troubles with CONTROL ADD "Custom". I've created and registered a class successfully using:
    Code:
       szName 		= "MyControl"
       wc.cbSize 		= SizeOf(wc)
       wc.style 		= %CS_HREDRAW OR %CS_VREDRAW OR %CS_PARENTDC OR %CS_GLOBALCLASS
       wc.lpfnWndProc 	= CodePtr(frmMain_DLGPROC)  
       wc.cbClsExtra 	= 0
       wc.cbWndExtra 	= 0
       wc.hInstance 	= GetModuleHandle (ByVal 0)
       wc.hIcon 		= %NULL
       wc.hCursor 		= LoadCursor(%NULL, ByVal %IDC_ARROW )
       wc.hbrBackground 	= GetStockObject(%NULL_BRUSH)
       wc.lpszMenuName 	= %NULL
       wc.lpszClassName 	= VarPtr(szName)
       wc.hIconSm 		= %NULL
    	
       lSuccess = RegisterClassEx(wc)
    But when I create the control using:
    Code:
       Control Add "MyControl", hDlg, %MYCONTROL, "Title", 1,50,300,150, %WS_VISIBLE Or %WS_TABSTOP Or %WS_CHILD, 0&
    no hWnd to the control is created: CONTROL HANDLE returns 0. In addition, ERR is 0 after the CONTROL ADD call.

    The actual "control" is a DLL that has it's own functions for drawing and updating the control contents; all it needs
    is a valid control hWnd. For example, the C code for creating & presenting the control is just three lines:
    Code:
       hwndControl = GetDlgItem(hWnd, IDCUSTOM);
       hControlData = ControlCreate();    // DLL call: Creates the control and returns a handle to the control's data
       ControlAttachWindow(hControlData, hwndControl);    // DLL call: Attaches the control to the control's window handle
    This leads me to wonder, are there certain types of "custom" controls that aren't compatible with DDT? If not, anyone have
    any idea what I'm doing wrong?

    Thanks!



    ------------------
    Mark Newman
Working...
X