News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

HIDE Dialog Template

Started by griviel, August 06, 2009, 06:42:27 PM

Previous topic - Next topic

griviel

Hello all,

This is my first post, I'm pretty new to ASM or shall I say programming in general. But I really think I am learning and understanding
HLA pretty well.

I'm trying to get 2 dialogs to work with the HIDE Dialog template. The first one is fine but when I want the second one to open, from a button, I can't seem to get it to work without crashing the app. I think I'm not understanding how to register a 2nd class. I've been trying to figure this out for the last few days. I've searched all over the forum and a few other places, saw a few samples in MASM and a few non-resource ones, but not one HIDE/HLA version. I tried my best to understand and mimic the MASM version, but I feel I'm not there yet. Any help would be great :)

Thanks
Griviel


Sevag.K

What exactly are you trying to do?  Post some code and let us know please.

griviel

Oh my mistake, I guess it's really not that clear. Here is the HIDE project sample in a zip.
Two dialog resources, one main, one second, can't control the second one
after I open with a button.

I have changed the code around so many times, i just put it back to my stuck state.



Thanks
griviel

[attachment deleted by admin]

Sevag.K

I see.  The problem is that you've mixed message handling styles.  The dialog template is designed to work with jump tables so it is advisable to stay within the set parameters.  The advantage of having the jump tables is that it is easier to add new command items simply by extending the list.  In this regard, the actual WndProc should not be altered unless for very special circumstances.

First thing to do is add your button to the command list:


// WM_COMMAND message table, wparam items go here
command_table :MsgProcPtr_t; @nostorage;
MsgProcPtr_t
MsgProcPtr_t:[ IDM_FILE_QUIT, &Cmd_File_Quit ],
MsgProcPtr_t:[ DC_BTN1, &Cmd_Press_Button],  // <-- added new command here

// add more commands here
MsgProcPtr_t:[ 0, NULL ];



Now we need to add a procedure for Cmd_Press_Button


procedure Cmd_Press_Button ( hwin:dword; wparam:dword; lparam:dword );
begin Cmd_Press_Button;

// open a dialog
w.DialogBoxParam (hinst, val IDD_DLG1, NULL, &DlgProc, false);

end Cmd_Press_Button;


Now for the dialog, you can copy the template WndProc, but you cannot use the same message table or the same command table!  They have to be unique for each window procedure in this case.  You also treat a generic dialog box a little different from a user defined and registered window/dialog and the dialog closing message handler:

Adding two new tables for the dialog:


dialog_message_table :MsgProcPtr_t; @nostorage;
MsgProcPtr_t
MsgProcPtr_t:[ w.WM_COMMAND, &Dlg_Command ],
MsgProcPtr_t:[ w.WM_CLOSE, &Dlg_Close ],

// add more messages here
MsgProcPtr_t:[ 0, NULL ]; // This marks the end of the list.

dialog_command_table :MsgProcPtr_t; @nostorage;
MsgProcPtr_t

// add more commands here
MsgProcPtr_t:[ 0, NULL ];

...

procedure Dlg_Close( hwin:dword; wparam:dword; lparam:dword );
begin Dlg_Close;

// close the dialog
w.EndDialog(hwin, wparam);
mov( true , eax);

end Dlg_Close;



That pretty much sums it up.  This is the entire code, note the changes to WndProc and DlgProc, also in this case, you can open as many dialogs as you want by clicking the button many times and use the same message/command tables for all of them since they are clones.



// HIDE template
// Window as Dialog with menu.
// Version 5.0
// Styled similar to WinMain from WPA

program Window;
#includeonce("w.hhf")

type
// Message and dispatch table related definitions:
 
MsgProc_t: procedure( hwnd:dword; wParam:dword; lParam:dword );

MsgProcPtr_t:
record
MessageValue :dword;
MessageHndlr :MsgProc_t;
endrecord;
endtype;


static
align(4);
hinst :dword; // instance handle
hwnd :dword; // main window handle

wc :w.WNDCLASSEX; // window class structure
msg :w.MSG; // message record
endstatic;

const // dialog & control constants
// dialog
IDD_DLG := 1000;

// menu
IDR_MENU := 1000;
IDM_FILE := 1001;
IDM_FILE_QUIT := 1002;

DC_BTN1 := 1003;
IDD_DLG1 := 1004;

endconst;

readonly // message tables.  change this section to static if you wish to change pointers during run-time


ClassName :string:="MAINCLASS"; // you may substitude your own name for "MAINCLASS"
AppName :string:="DIALOGAPP"; // you may substitude your own name for "TEMPAPP"


// main window message table

message_table :MsgProcPtr_t; @nostorage;
MsgProcPtr_t
MsgProcPtr_t:[ w.WM_COMMAND, &Msg_Command ],
MsgProcPtr_t:[ w.WM_DESTROY, &Msg_Destroy ],
MsgProcPtr_t:[ w.WM_CLOSE, &Msg_Close ],
MsgProcPtr_t:[ w.WM_INITDIALOG, &Msg_InitDialog ],
// add more messages here
MsgProcPtr_t:[ 0, NULL ]; // This marks the end of the list.

// WM_COMMAND message table, wparam items go here
command_table :MsgProcPtr_t; @nostorage;
MsgProcPtr_t
MsgProcPtr_t:[ IDM_FILE_QUIT, &Cmd_File_Quit ],
MsgProcPtr_t:[ DC_BTN1, &Cmd_Press_Button],

// add more commands here
MsgProcPtr_t:[ 0, NULL ];


dialog_message_table :MsgProcPtr_t; @nostorage;
MsgProcPtr_t
MsgProcPtr_t:[ w.WM_COMMAND, &Dlg_Command ],
MsgProcPtr_t:[ w.WM_CLOSE, &Dlg_Close ],

// add more messages here
MsgProcPtr_t:[ 0, NULL ]; // This marks the end of the list.

dialog_command_table :MsgProcPtr_t; @nostorage;
MsgProcPtr_t

// add more commands here
MsgProcPtr_t:[ 0, NULL ];

endreadonly;

procedure Dlg_Close( hwin:dword; wparam:dword; lparam:dword );
begin Dlg_Close;

// close the dialog
w.EndDialog(hwin, wparam);
mov( true , eax);

end Dlg_Close;


procedure Dlg_Command ( hwin:dword; wparam:dword; lparam:dword );
@nodisplay;
begin Dlg_Command;

mov(wparam,ecx);
mov(ecx,edx);
movzx(cx,ecx);
shr(16,edx);

IF ( edx = w.BN_CLICKED || edx = 1 ) THEN

// control or accelerator

mov(&dialog_command_table,edx);
mov(ecx,eax);

FOREVER
mov( (type MsgProcPtr_t [edx]).MessageHndlr, ecx );
IF ( ecx = 0 ) THEN
BREAK;

ELSEIF ( eax = (type MsgProcPtr_t [edx]).MessageValue ) THEN

push( hwin );
push( wparam );
push( lparam );
call( ecx );
sub(eax,eax);
BREAK;
ENDIF;
add( @size( MsgProcPtr_t ), edx );
ENDFOR;

ENDIF;

end Dlg_Command;


procedure DlgProc ( lparam:dword; wparam:dword; umsg:uns32; dwin:dword ); @nodisplay;

begin DlgProc;

mov(umsg,eax);
mov(&dialog_message_table,edx);

FOREVER
mov( (type MsgProcPtr_t [edx]).MessageHndlr, ecx );
IF( ecx = 0 ) THEN
xor(eax, eax);
EXIT DlgProc;

ELSEIF( eax = (type MsgProcPtr_t [edx]).MessageValue ) THEN

push( dwin );
push( wparam );
push( lparam );
call( ecx );
sub(eax,eax);
BREAK;
ENDIF;
add( @size( MsgProcPtr_t ), edx );
ENDFOR;

end DlgProc;

procedure Error ( error_msg:string ); @nodisplay;
begin Error;

w.MessageBox(NULL,error_msg,"ERROR",w.MB_OK | w.MB_ICONERROR );

cmp(hwnd,0);
je _nowindow;
w.PostQuitMessage(0);
exit Error;

_nowindow:
xor(eax,eax);

end Error;

procedure Cmd_File_Quit ( hwin:dword; wparam:dword; lparam:dword );
begin Cmd_File_Quit;


w.SendMessage (hwin, w.WM_CLOSE, 0, 0 );

end Cmd_File_Quit;

procedure Cmd_Press_Button ( hwin:dword; wparam:dword; lparam:dword );
begin Cmd_Press_Button;

// open a dialog
w.DialogBoxParam (hinst, val IDD_DLG1, NULL, &DlgProc, false);

end Cmd_Press_Button;


procedure Msg_InitDialog ( hwin:dword; wparam:dword; lparam:dword );
@nodisplay;
begin Msg_InitDialog;

mov(hwin, eax);
mov(eax, hwnd);
w.SetWindowText(hwin, AppName);

// window creation initialization goes here

end Msg_InitDialog;


procedure Msg_Close ( hwin:dword; wparam:dword; lparam:dword );
@nodisplay;
begin Msg_Close;

// user selects close button
w.SendMessage(hwin, w.WM_DESTROY, 0, 0 );

end Msg_Close;


procedure Msg_Destroy ( hwin:dword; wparam:dword; lparam:dword );
@nodisplay;
begin Msg_Destroy;

w.PostQuitMessage( NULL );

end Msg_Destroy;



procedure Msg_Command ( hwin:dword; wparam:dword; lparam:dword );
@nodisplay;
begin Msg_Command;

mov(wparam,ecx);
mov(ecx,edx);
movzx(cx,ecx);
shr(16,edx);

IF ( edx = w.BN_CLICKED || edx = 1 ) THEN

// control or accelerator

mov(&command_table,edx);
mov(ecx,eax);

FOREVER
mov( (type MsgProcPtr_t [edx]).MessageHndlr, ecx );
IF ( ecx = 0 ) THEN
BREAK;

ELSEIF ( eax = (type MsgProcPtr_t [edx]).MessageValue ) THEN

push( hwin );
push( wparam );
push( lparam );
call( ecx );
sub(eax,eax);
BREAK;
ENDIF;
add( @size( MsgProcPtr_t ), edx );
ENDFOR;

ENDIF;

end Msg_Command;


procedure WndProc ( lparam:dword; wparam:dword; umsg:uns32; hwin:dword ); @nodisplay;
// main window message handler

begin WndProc;


mov(umsg,eax);
mov(&message_table,edx);

FOREVER
mov( (type MsgProcPtr_t [edx]).MessageHndlr, ecx );
IF( ecx = 0 ) THEN
w.DefWindowProc( hwin, umsg, wparam, lparam );
EXIT WndProc;

ELSEIF( eax = (type MsgProcPtr_t [edx]).MessageValue ) THEN

push( hwin );
push( wparam );
push( lparam );
call( ecx );
sub(eax,eax);
BREAK;
ENDIF;
add( @size( MsgProcPtr_t ), edx );
ENDFOR;

end WndProc;


begin Window;

w.GetModuleHandle( NULL );
mov( eax, hinst );

// main window created here
// describe and register the window class
mov( @size(w.WNDCLASSEX), wc.cbSize );
mov( w.CS_HREDRAW | w.CS_VREDRAW, wc.style );
mov( &WndProc, wc.lpfnWndProc );
mov( NULL, wc.cbClsExtra );
mov( w.DLGWINDOWEXTRA, wc.cbWndExtra );
mov( hinst, wc.hInstance );
mov( w.COLOR_BTNFACE+1, wc.hbrBackground );
mov( IDR_MENU, wc.lpszMenuName );
mov( ClassName, wc.lpszClassName );

w.LoadIcon( NULL, val w.IDI_APPLICATION );
mov( eax, wc.hIcon );
mov( eax, wc.hIconSm );
w.LoadCursor( NULL, val w.IDC_ARROW );
mov( eax,wc.hCursor );
w.RegisterClassEx( wc );
or(eax,eax);
jnz _registerok;
Error( "Unable to register window class");
exit Window;

_registerok:
w.CreateDialogParam(
hinst, // hInstance
val IDD_DLG, // dialog ID number
NULL, // parent window, NULL = desktop
&WndProc, // call-back procedure
NULL // user defined initialization value
);


cmp(eax,0);
jne _windowok;
Error( "Unable to create window");
exit Window;

_windowok:

w.ShowWindow( hwnd, w.SW_SHOWNORMAL );
w.UpdateWindow( hwnd );

FOREVER
w.GetMessage(msg,NULL,0,0);
breakif( ! eax );

w.TranslateMessage( msg );
w.DispatchMessage( msg );
ENDFOR;

mov( msg.wParam, eax );
_exit:

end Window;




griviel

Wow, I can understand everything you did and why you did it that way. Seems working with resources
is a bit more work when learning at first, but helpful in understanding how things work.

The HIDE templates are pretty amazing for beginners like me, I feel I'm well on my way now  :bg

Thanks
Griviel