Author Topic: Subclassing in a dialog  (Read 673 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Hero Member
  • *****
  • Posts: 941
Subclassing in a dialog
« on: October 09, 2018, 05:52:36 AM »
Hello,

I doubt a bit about the benefits of subclassing / superclassing controls in dialogs, but it is possible to some extent.

This is a sample using Edit and Label control. It will work in 32-bit and 64-bit. It uses the approach for the versions of ComCtl32.dll prior to version 6.

Code: (o2) [Select]
' Subclassing in a Dialog
$ filename "DlgSubclass.exe"

'uses rtl32
'uses rtl64

'% review
uses dialogs
 
% GWLP_WNDPROC= -4
% DS_3DLOOK  0x0004L
% DS_NOFAILCREATE  0x0010L
% DS_MODALFRAME  0x80L

'Equates
% IDC_EDIT    = 1001
% IDC_LABEL   = 1002

sys hEdit
sys hLabel


'=================================
sub WinMain()
 
 Dialog( 0, 0, 302, 160, "Edit Subclass in a Dialog",
         WS_POPUP | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_CLIPSIBLINGS | WS_VISIBLE | DS_MODALFRAME | DS_3DLOOK | DS_NOFAILCREATE | DS_SETFONT | DS_CENTER,
          8, "MS Sans Serif",
          WS_EX_CONTROLPARENT | WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR)
     
    EDITTEXT("", IDC_EDIT, 8, 8, 217, 84,
                       WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | WS_VISIBLE | ES_WANTRETURN | ES_LEFT | WS_BORDER,
                       WS_EX_CLIENTEDGE)

    LText( "", IDC_LABEL, 8, 110, 120, 24)

    CreateModalDialog( null, @DlgProc, 0)     
end function
   
WinMain()
'=================================

function DlgProc( sys hDlg, uint uMsg, sys wParam, lParam ) as sys callback
   hEdit= GetDlgItem(hDlg, IDC_EDIT)
   hLabel=GetDlgItem(hDlg, IDC_LABEL)

   select case uMsg

    case WM_INITDIALOG
       SetProp(hEdit, "OldEditProc", SetWindowLongPtr(hEdit, GWLP_WNDPROC, @EditProc))

    case WM_CLOSE
       'Remove control subclassing
       RemoveProp(hEdit, "OldEditProc", GetWindowLongPtr(hEdit, GWLP_WNDPROC, @EditProc))       
           
       EndDialog( hDlg, null )
    end select   
 
    return 0
end function

'======================================
' Subclass procedure for the Edit control to detect what  ASCII values were key in
function EditProc(sys hDlg, uint wMsg, sys wParam, lParam) as sys callback

   select case wMsg       
        case WM_KEYDOWN
           SetWindowText (hLabel, "You have entered ASCII " str(wParam))
   end select

   return CallWindowProc(GetProp(hEdit, "OldEditProc"), hEdit, wMsg, wParam, lParam)

end function

Aurel

  • Sr. Member
  • ****
  • Posts: 443
Re: Subclassing in a dialog
« Reply #1 on: February 13, 2020, 06:17:38 AM »
Hello Arnold

I recveive strange errors in this example.
First you missmatch

CreateModalDialog( null, @DlgProc, 0, 0)  '<- missmatch here
   'CreateModalDialog( sys hParent, sys *lpDialogProc, dwInitParam, lpdt) as sys 


Ok that is not problematic then , i just add one more NULL on the end.
then
GetDialog item is not declared in include "Dialogs"
then i get "too many brackets" even there are no to many as i see here:

 RemoveProp(hEdit, "OldEditProc", GetWindowLongPtr(hEdit, GWLP_WNDPROC, @EditProc))   

I see that you have working example so i am wandering how?
why i asking ?
I recently trying to subclass richedit control to get margin and line numbers so i am looking into
something similar...
Are you interested maybe ?   :)

thanks
my site:BLOG and FORUM
https://aurelsoft.ucoz.com/

Aurel

  • Sr. Member
  • ****
  • Posts: 443
Re: Subclassing in a dialog
« Reply #2 on: February 13, 2020, 08:07:02 AM »
I found some errors in includes and in declaration
then after fixing , o2 say Ok ,but when i try to run then program just crush.

this one is critical

RemoveProp Lib "user32.dll" Alias "RemovePropA" (ByVal hWnd As Long, ByVal lpString As String) As Long

and we have in program this:

RemoveProp(hEdit, "OldEditProc", GetWindowLongPtr(hEdit, GWLP_WNDPROC, @EditProc))

...so i don't know how this even compile  ::)
my site:BLOG and FORUM
https://aurelsoft.ucoz.com/

Aurel

  • Sr. Member
  • ****
  • Posts: 443
Re: Subclassing in a dialog
« Reply #3 on: February 13, 2020, 08:16:00 AM »
Here is my code :
Code: [Select]
' Subclassing in a Dialog
$ filename "DlgSubclass.exe"

uses rtl32
'uses rtl64

'% review
uses dialogs
! SetWindowLong    Lib "user32.dll" Alias "SetWindowLongA"(hwnd AS INT,nIndex AS INT,dwNewLong AS INT) as INT
! SetWindowLongPtr Lib "user32.dll" Alias "SetWindowLongA"(ByVal hWnd As Int,byVal nIndex As Int, ByVal dwNewLong As Int) As Int
! SetProp          Lib "user32.dll" Alias "SetPropA" (ByVal hWnd As Long, ByVal lpString As String, ByVal hData As Long) As Long
! GetProp          Lib "user32.dll" Alias "GetPropA" (ByVal hWnd As Long, ByVal lpString As String) As Long
! CallWindowProc   Lib "user32.dll" Alias "CallWindowProcA"(lpPrevWndFunc AS INT,hWnd AS INT,Msg AS INT,wParam AS INT,lParam AS INT) as INT
! RemoveProp Lib "user32.dll" Alias "RemovePropA" (ByVal hWnd As Long, ByVal lpString As String) As Long

% GWLP_WNDPROC= -4
% DS_3DLOOK  0x0004L
% DS_NOFAILCREATE  0x0010L
% DS_MODALFRAME  0x80L
% DS_CENTER = 2048

'Equates
% IDC_EDIT    = 1001
% IDC_LABEL   = 1002

sys hEdit
sys hLabel
int hDlg

'=================================
sub WinMain()
 
 hDlg = Dialog( 0, 0, 302, 160, "Edit Subclass in a Dialog",
         WS_POPUP | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_CLIPSIBLINGS | WS_VISIBLE | DS_MODALFRAME | DS_3DLOOK | DS_NOFAILCREATE | DS_SETFONT | DS_CENTER,
          8, "MS Sans Serif",
          WS_EX_CONTROLPARENT | WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR)
     
    EDITTEXT("", IDC_EDIT, 8, 8, 217, 84,
                       WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | WS_VISIBLE | ES_WANTRETURN | ES_LEFT | WS_BORDER,
                       WS_EX_CLIENTEDGE)

    LText( "", IDC_LABEL, 8, 110, 120, 24)

    CreateModalDialog( null, @DlgProc, 0, 0)  '<- missmatch here
   'CreateModalDialog( sys hParent, sys *lpDialogProc, dwInitParam, lpdt) as sys   
end sub
   
WinMain()
'=================================

function DlgProc( sys hDlg, uint uMsg, sys wParam, lParam ) as sys callback
   hEdit  = GetDlgItem(hDlg, IDC_EDIT)
   hLabel = GetDlgItem(hDlg, IDC_LABEL)

   select case uMsg

    case WM_INITDIALOG
       SetProp(hEdit, "OldEditProc", SetWindowLongPtr(hEdit, GWLP_WNDPROC, @EditProc))

    case WM_CLOSE
       'Remove control subclassing
       'RemoveProp(hEdit, "OldEditProc", GetWindowLongPtr(hEdit, GWLP_WNDPROC, @EditProc)) 
       RemoveProp( hEdit, "OldEditProc")
           
       EndDialog( hDlg, null )
    end select   
 
    return 0
end function

'======================================
' Subclass procedure for the Edit control to detect what  ASCII values were key in
function EditProc(sys hDlg, uint wMsg, sys wParam, lParam) as sys callback

   select case wMsg       
        case WM_KEYDOWN
           SetWindowText (hLabel, "You have entered ASCII " str(wParam))
   end select

   return CallWindowProc(GetProp(hEdit, "OldEditProc"), hEdit, wMsg, wParam, lParam)

end function
my site:BLOG and FORUM
https://aurelsoft.ucoz.com/

Arnold

  • Hero Member
  • *****
  • Posts: 941
Re: Subclassing in a dialog
« Reply #4 on: February 13, 2020, 10:03:52 AM »
Hi Aurel,

it seems that you still use an older version? Dialogs.inc has changed in the meantime, only three parameters are necessary, the fourth argument should be omitted, it points automatically to a DLGTEMPLATE structure. If you use an older version you must look in the examples there how lpdt is created and applied.

You do not include corewin, but your declarations seem to be wrong. Look in win32help file e.g. for RemoveProp: -> lpString. There are two alternatives. Corewin unprototyped solves this better than your prototyping. You also forgot GetWindowLong. For 32-bit GetWindowLongPtr and SetWindowLongPtr is not available in user32.dll.

This is my re-modyfied code, which again works in version 0.2.8 (32-bit only):

Code: [Select]
' Subclassing in a Dialog
$ filename "DlgSubclass.exe"

'uses rtl32

'% review
uses dialogs
! SetWindowLong    Lib "user32.dll" Alias "SetWindowLongA"
! GetWindowLong    lib "user32.dll" alias "GetWindowLongA"
! SetProp          Lib "user32.dll" Alias "SetPropA"
! GetProp          Lib "user32.dll" Alias "GetPropA"
! CallWindowProc   Lib "user32.dll" Alias "CallWindowProcA"
! RemoveProp Lib "user32.dll" Alias "RemovePropA"

% GWLP_WNDPROC= -4
% DS_3DLOOK  0x0004L
% DS_NOFAILCREATE  0x0010L
% DS_MODALFRAME  0x80L
% DS_CENTER = 2048

'Equates
% IDC_EDIT    = 1001
% IDC_LABEL   = 1002

sys hEdit
sys hLabel
int hDlg

'=================================
sub WinMain()
 
 hDlg = Dialog( 0, 0, 302, 160, "Edit Subclass in a Dialog",
         WS_POPUP | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_CLIPSIBLINGS | WS_VISIBLE | DS_MODALFRAME | DS_3DLOOK | DS_NOFAILCREATE | DS_SETFONT | DS_CENTER,
          8, "MS Sans Serif",
          WS_EX_CONTROLPARENT | WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR)
     
    EDITTEXT("", IDC_EDIT, 8, 8, 217, 84,
                       WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | WS_VISIBLE | ES_WANTRETURN | ES_LEFT | WS_BORDER,
                       WS_EX_CLIENTEDGE)

    LText( "", IDC_LABEL, 8, 110, 120, 24)

    CreateModalDialog( null, @DlgProc, 0)

end sub
   
WinMain()
'=================================

function DlgProc( sys hDlg, uint uMsg, sys wParam, lParam ) as sys callback
   hEdit  = GetDlgItem(hDlg, IDC_EDIT)
   hLabel = GetDlgItem(hDlg, IDC_LABEL)

   select case uMsg

    case WM_INITDIALOG
       SetProp(hEdit, "OldEditProc", SetWindowLongPtr(hEdit, GWLP_WNDPROC, @EditProc))

    case WM_CLOSE
       'Remove control subclassing
       RemoveProp(hEdit, "OldEditProc", GetWindowLongPtr(hEdit, GWLP_WNDPROC, @EditProc))
       'RemoveProp( hEdit, "OldEditProc")
           
       EndDialog( hDlg, null )
    end select   
 
    return 0
end function

'======================================
' Subclass procedure for the Edit control to detect what  ASCII values were key in
function EditProc(sys hDlg, uint wMsg, sys wParam, lParam) as sys callback

   select case wMsg       
        case WM_KEYDOWN
           SetWindowText (hLabel, "You have entered ASCII " str(wParam))
   end select

   return CallWindowProc(GetProp(hEdit, "OldEditProc"), hEdit, wMsg, wParam, lParam)

end function

You will find information about subclassing here:

https://docs.microsoft.com/en-us/windows/win32/controls/subclassing-overview

There is an advanced and an old approach for subclassing. In the example of the first message above I used the old subclassing method.

Roland

Aurel

  • Sr. Member
  • ****
  • Posts: 443
Re: Subclassing in a dialog
« Reply #5 on: February 13, 2020, 10:27:39 AM »
OK Arnold
I will try your version with latest 0.2.8 vaesion 32bit.
We have really too much include versions and what is the strangst , declarations are in conflict with
standard VB versions published on many places on the internet.
oh my...ok  ::)
my site:BLOG and FORUM
https://aurelsoft.ucoz.com/

Aurel

  • Sr. Member
  • ****
  • Posts: 443
Re: Subclassing in a dialog
« Reply #6 on: February 13, 2020, 10:41:06 AM »
Yipie
Thanks Arnold ..
finally work in 0.2.8 32bit even ,...i still not tested how anything work on my win7_64bit  ::)

About subclassing ,well like you said i was sceptic, i found one old code from PureBasic
so i am in translation to o2..i hope that will work for line numbering in richedit control.  :D
my site:BLOG and FORUM
https://aurelsoft.ucoz.com/

Aurel

  • Sr. Member
  • ****
  • Posts: 443
Re: Subclassing in a dialog
« Reply #7 on: February 14, 2020, 12:08:38 PM »
Just new unexpected discovery on masm32 forum.
Example work like a charm...code is in masm32...so i will not post it here.
I hope that i know how to translate it to o2 code  :D
masm32 code is here:
https://aurelsoft.ucoz.com/forum/3-26-1#45
« Last Edit: February 15, 2020, 02:05:13 AM by Aurel »
my site:BLOG and FORUM
https://aurelsoft.ucoz.com/