PowerBASIC Peer Support Forums
 

Go Back   PowerBASIC Peer Support Forums > User to user Discussions > Dynamic Dialog Tools (DDT)

Dynamic Dialog Tools (DDT) Discussion is limited to GUI development using DDT. Comments about SDK programming are allowed only for functionality which enhances DDT.

Reply
 
Thread Tools Display Modes
  #1  
Old Dec 1st, 2011, 02:02 PM
Chris Holbrook Chris Holbrook is offline
Member
 
Join Date: Aug 2005
Location: in Hiding
Posts: 6,398
Simple way to subclass controls

Code is here http://www.powerbasic.com/support/pb...686#post393686

This is an attempt to make the code as simple and easily deployed as possible.

Any number of controls of the specified type can be subclassed in the same way - similar effect to superclassing.
Reply With Quote
  #2  
Old Dec 1st, 2011, 02:10 PM
Michael Mattias Michael Mattias is offline
Member
 
Join Date: Aug 1998
Location: Racine WI USA
Posts: 36,263
Code:
macro mAddSubclassedTextBox (CtlId, txt, X, Y, W, H)
    macrotemp oldproc
    dim oldproc as dword
    control add textbox, hiddendlghandle, CtlId, txt, X, Y, W, H
    oldproc = setwindowlong(getdlgitem(hiddendlghandle, CtlId), %GWL_WNDPROC, codeptr(TBsubclassCB))
....

You might want to make the callback procname one of the macro parameters. That would allow you to use the same macro but specify different callback procedures for different "subclassed textbox controls" on the same screen.
Reply With Quote
  #3  
Old Dec 1st, 2011, 03:59 PM
Chris Holbrook Chris Holbrook is offline
Member
 
Join Date: Aug 2005
Location: in Hiding
Posts: 6,398
Quote:
Originally Posted by Michael Mattias View Post
You might want to make the callback procname one of the macro parameters. That would allow you to use the same macro but specify different callback procedures for different "subclassed textbox controls" on the same screen.
Yes, but that throws the onus of message handling back on the subclass proc. My preference is to do it in the dialog proc, for example like:

Code:
        case %FROM_SUBCLASSED_TEXTBOX
            select case as long cb.wparam ' control id is returned in cb.wparam
                 case 1001, 1002, 1009
                        ' some processing
                 case 1003, 1004, 1005, 1006, 1007, 1008
                        ' some other processing
            end select

Last edited by Chris Holbrook; Dec 1st, 2011 at 04:07 PM.
Reply With Quote
  #4  
Old Dec 1st, 2011, 07:19 PM
Michael Mattias Michael Mattias is offline
Member
 
Join Date: Aug 1998
Location: Racine WI USA
Posts: 36,263
>Yes, but that throws the onus of message handling back on the subclass proc.

Um, isn't that the whole idea of subclassing? That the programmer can handle notification messages not otherwise available in an application-specific manner?

I have applications which have multiple controls sharing a subclass proc, and applications where different controls of the same class use different subclass procedures.

"procname=macro param" was just a thought....a little extra "Power."
Reply With Quote
  #5  
Old Dec 1st, 2011, 07:34 PM
Chris Holbrook Chris Holbrook is offline
Member
 
Join Date: Aug 2005
Location: in Hiding
Posts: 6,398
Quote:
Originally Posted by Michael Mattias View Post
>Yes, but that throws the onus of message handling back on the subclass proc.

Um, isn't that the whole idea of subclassing? ...
That is how subclassing is implemented, but it is not always friendly to the objectives of the application, and in such cases a method of directing events which can only be trapped by subclassing/superclassing to a single procedure is appropriate.

The comments at the top of the code make my purpose clear, "...example to show how subclassing can be used to reflect messages received
by a control to its parent dialog..."

BTW can you think of an alternative (to subclassing) way of turning off the right-click menu on a textbox? My brain has already signed off...
Reply With Quote
  #6  
Old Dec 2nd, 2011, 12:30 AM
Gary Beene Gary Beene is online now
Administrator
 
Join Date: May 2008
Location: Dallas, Tx
Posts: 9,868
Hi Chris(H)!
Re:
Quote:
... alternative (to subclassing) way of turning off the right-click menu on a textbox?
My first thought was that there is a WM_InitMenuPopup message sent when a popup appears, but it seems that message is sent to the child window, not the parent. Under DDT that takes subclassing to capture, but can't it be captured in an SDK app? I'm not familiar enough with SDK code to know for sure.

My next idea was this code, which works, but poorly because it flashes the textbox control:
Code:
'Compilable Example:
#Compile Exe
#Dim All
#Include "Win32API.inc"
Global hDlg,hTextBox As Dword
%IDC_TextBox = 500
Function PBMain() As Long
   Dialog New Pixels, 0, "Parent",300,300,200,100, %WS_OverlappedWindow To hDlg
   Control Add TextBox, hDlg, %IDC_TextBox, "Hello",10,10,180,80
   Control Handle hDlg, %IDC_TextBox To hTextBox
   Dialog Show Modal hDlg Call DlgProc
End Function

CallBack Function DlgProc() As Long
   Select Case Cb.Msg
     Case %WM_SetCursor  'MouseMove
         Select Case Hi(Word, Cb.LParam)
            Case %WM_RButtonDown
                If GetDlgCtrlID (Cb.WParam) = %IDC_TextBox Then
                    Control Disable hDlg, %IDC_TextBox
                End If
            Case %WM_RButtonUp
                Control Enable hDlg, %IDC_TextBox
         End Select
   End Select
End Function
I'll think on it some more.
__________________
Reply With Quote
  #7  
Old Dec 2nd, 2011, 12:37 AM
Gary Beene Gary Beene is online now
Administrator
 
Join Date: May 2008
Location: Dallas, Tx
Posts: 9,868
Oh, and I also tried sending the TextBox a WM_CancelMode message (instead of the Control Disable statement. That didn't work.

MSDN had this, which suggested it might work:
Quote:
When the WM_CANCELMODE message is sent, the DefWindowProc function cancels internal processing of standard scroll bar input, cancels internal menu processing, and releases the mouse capture.
It seems like there ought to be something that would work by replacing the Control Disable statement in my code, but it's not obvious just yet.
__________________
Reply With Quote
  #8  
Old Dec 2nd, 2011, 12:45 AM
Gary Beene Gary Beene is online now
Administrator
 
Join Date: May 2008
Location: Dallas, Tx
Posts: 9,868
Hey Chris(H)!
This is much closer - the very tiniest of flicker in Win7, Aero mode - and slightly more in non-Aero mode.
Code:
'Compilable Example:
#Compile Exe
#Dim All
#Include "Win32API.inc"
Global hDlg,hTextBox As Dword
%IDC_TextBox = 500
Function PBMain() As Long
   Dialog New Pixels, 0, "Parent",300,300,200,100, %WS_OverlappedWindow To hDlg
   Control Add TextBox, hDlg, %IDC_TextBox, "Hello",10,10,180,80
   Control Handle hDlg, %IDC_TextBox To hTextBox
   Dialog Show Modal hDlg Call DlgProc
End Function

CallBack Function DlgProc() As Long
   Select Case Cb.Msg
     Case %WM_SetCursor  'MouseMove
         Select Case Hi(Word, Cb.LParam)
            Case %WM_RButtonUp
                If GetDlgCtrlID (Cb.WParam) = %IDC_TextBox Then
                    PostMessage hTextBox, %WM_CancelMode, 0, 0
                End If
         End Select
   End Select
End Function
Basically this code closes the menu as soon as it opens. What we're looking for is to stop it from appearing in the first place.
__________________
Reply With Quote
  #9  
Old Dec 2nd, 2011, 01:13 AM
Rodney Hicks Rodney Hicks is offline
Member
 
Join Date: Apr 2007
Location: Winnipeg, Manitoba, Canada
Posts: 3,083
Could PeekMessage be used to block the %WM_RButtonDown or %WM_RButtonUp as required on that particular control?
__________________
Rod
"To every unsung hero in the universe
To those who roam the skies and those who roam the earth
To all good men of reason may they never thirst " - from "Heaven Helpt the Devil" by G. Lightfoot
Reply With Quote
  #10  
Old Dec 2nd, 2011, 02:37 AM
Dave Biggs Dave Biggs is offline
Member
 
Join Date: Feb 2001
Location: Australia
Posts: 2,219
Could always use a hook
__________________
Rgds, Dave
Reply With Quote
  #11  
Old Dec 2nd, 2011, 08:01 AM
Gary Beene Gary Beene is online now
Administrator
 
Join Date: May 2008
Location: Dallas, Tx
Posts: 9,868
Hi Dave,
I thought of that (I like my new hammer!), but don't know enough about menus to know what class (or other window info) to look for. I'll go nose around MSDN for some clues.
__________________
Reply With Quote
  #12  
Old Dec 2nd, 2011, 08:07 AM
Gary Beene Gary Beene is online now
Administrator
 
Join Date: May 2008
Location: Dallas, Tx
Posts: 9,868
Hi Dave/Chris(H),
Ok, I cheated. I didn't go to MSDN. I just iterated the class names that came up and found #32768, tried it, and it seems to do the trick with no flickering.

Code:
'Compilable Example:
#Compile Exe
#Dim All
#Include "Win32API.inc"
Global hDlg,hTextBox,ghHook As Dword
%IDC_TextBox = 500
Function PBMain() As Long
   Dialog New Pixels, 0, "Parent",300,300,200,100, %WS_OverlappedWindow To hDlg
   Control Add TextBox, hDlg, %IDC_TextBox, "Hello",10,10,180,80
   Control Handle hDlg, %IDC_TextBox To hTextBox
   Dialog Show Modal hDlg Call DlgProc
End Function

CallBack Function DlgProc() As Long
   Select Case Cb.Msg
     Case %WM_SetCursor  'MouseMove
         Select Case Hi(Word, Cb.LParam)
            Case %WM_RButtonUp
                If GetDlgCtrlID (Cb.WParam) = %IDC_TextBox Then
                    ghHook = SetWindowsHookEx(%WH_CBT, CodePtr(MenuProc), GetModuleHandle(""), GetCurrentThreadId)
                End If
         End Select
   End Select
End Function

Function MenuProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Local szTemp As Asciiz * %Max_Path
    Function = CallNextHookEx(ByVal ghHook, ByVal nCode, ByVal wParam, ByVal lParam)
    If nCode < 0 Then Exit Function
    If nCode = %HCBT_ACTIVATE Then UnhookWindowsHookEx ghHook
    If nCode = %HCBT_CREATEWND Then
        GetClassName wParam, szTemp, %Max_Path      ' for each window / control as it is created
        If UCase$(szTemp) = "#32768" Then Function = 1   '@cst.cy = @cst.cy - 130                'dialog
    End If
End Function
__________________
Reply With Quote
  #13  
Old Dec 2nd, 2011, 08:14 AM
Gary Beene Gary Beene is online now
Administrator
 
Join Date: May 2008
Location: Dallas, Tx
Posts: 9,868
In hindsight, I went to MSDN and found this
Quote:
#32768 The Class For a menu.
__________________
Reply With Quote
  #14  
Old Dec 2nd, 2011, 08:51 AM
Michael Mattias Michael Mattias is offline
Member
 
Join Date: Aug 1998
Location: Racine WI USA
Posts: 36,263
Hmm, yesterday's "rich edit control in text mode" might have a solution....

Send EM_SETEVENTMASK, with the MSGFILTER structure referring to WM_RBUTTONUP and process the resulting EN_MSGFILTER notification....

Quote:
Return Value

If the control should process the event, the message returns a zero value.

If the control should ignore the event, the message returns a nonzero value.
It's a thought...
Reply With Quote
  #15  
Old Dec 2nd, 2011, 09:05 AM
Dave Biggs Dave Biggs is offline
Member
 
Join Date: Feb 2001
Location: Australia
Posts: 2,219
I was thinking of a different hammer - WH_MOUSE
Code:
#Dim All
#Include "win32API.inc"
 
Global ghMoHook As Dword
 
Function MouseProc(ByVal nCode As Long, ByVal wParam As Dword, ByVal lParam As Long) As Dword
 Local msh As MOUSEHOOKSTRUCT Ptr, szTemp As Asciiz * %Max_Path
  Function = CallNextHookEx(ghMoHook, nCode, wParam, lParam)  ' House keeping - call next hook in chain
  If nCode < 0 Then Exit Function
  If nCode = %HC_ACTION Then msh = lParam
    If wParam = %WM_RButtonUp Then GetClassName @msh.hwnd, szTemp, %Max_Path  ' for each window / control as it is created
      If UCase$(szTemp) = "EDIT" Then
      Function = 1
      SendMessage GetParent(@msh.hwnd), %WM_User + 501, wParam, lParam     ' Pass params to DlgProc
    End If
End Function
'------------------/MouseProc
 
CallBack Function DlgProc()
  Select Case As Long CbMsg
    Case %WM_InitDialog
      ghMoHook = SetWindowsHookEx(%WH_MOUSE, CodePtr(MouseProc), GetModuleHandle(""), GetCurrentThreadId)
 
    Case %WM_Destroy
      UnhookWindowsHookEx ghMoHook                         ' House Keeping - unhook mouse on exit
 
    Case %WM_Command
      Select Case CbCtlMsg
        Case %BN_Clicked
          If CbCtl = %IdCancel Then
            Dialog End CbHndl
          End If
      End Select
 
    Case %WM_User + 501                                   ' msg from mouseproc.
      Dialog Set Text CbHndl, Time$ + " Mouse R Key up"
 
  End Select
End Function
'------------------/
 
Function PBMain() As Long
 Local hDlg As Dword
  Dialog New 0, "Test", , , 240, 60, %WS_Caption Or %WS_SysMenu, 0 To hDlg
    Control Add TextBox, hDlg, 101, "Right-Click here :)", 15, 10, 205, 15
    Control Add Label,   hDlg, 102, "Mouse Hook Test", 15, 35, 135, 10
    Control Add Button,  hDlg, %IdCancel, "Done", 160, 35, 50, 15
    Control Set Focus hDlg, %IdCancel
 
  Dialog Show Modal hDlg, Call DlgProc
End Function
'------------------/PBMain
__________________
Rgds, Dave
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 07:38 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Copyright 1999-2011 PowerBASIC, Inc. All Rights Reserved.
Error in my_thread_global_end(): 1 threads didn't exit