Link to home
Start Free TrialLog in
Avatar of andla
andla

asked on

How do i recieve WM_INITDIALOG from a created button ?

Hi! please help me.

I create a button dynamically and subclass it. I don't recieve any WM_INITDIALOG. What should i do ?

Regards
Andla.
Avatar of jkr
jkr
Flag of Germany image

Beg my pardon, but a button is not a dialog at all - so how is it supposed to receive that message?
Ooops, "Beg my pardon" should of course be "Beg your pardon" .o)
Avatar of GGRUNDY
GGRUNDY

Try "Add virtual function" to override PreSubclassWindow. When you are writing your own control subclass it is almost what WM_INITDIALOG is for a dialog.
(PS. Try your windows questions in the EE "Windows Progaming" forum.)
Avatar of andla

ASKER

jkr>> You have recieved my pardon. ;-)

Sorry i suppose i meant WM_CREATE.
The funny thing is that if i use:
PostMessage(MyWindow,WM_INITDIALOG,0,0);
Then i recieve this in my callback function.
If i use WM_CREATE i don't. I suspect that the original procedure eats WM_CREATE so that my procedure don't get any piece. :-)


GGRUNDY>>Sorry i don't use MFC othewise this would probebly be what i want to do.


My approach to subclass a window is the following:

OldProc=(HWND)GetWindowLong( MyWindow,GWL_WNDPROC );
SetWindowLong( MyWindow, GWL_WNDPROC,
(DWORD)HookProc );

Regards
Andla
It is probably because WM_CREATE gets through BEFORE you actually subclass your window.  
Depending on what you want to do you can use other message,
for example WM_CTLCOLORBTN.  OF cause it gets called multiple times, but there are easy ways to avoid a this problem.

Hope it helps.
mblat it right.
Use your WM_CREATE code from Dialogs WM_INITDIALOG handler.

Also You can use just:
OldProc=(HWND)SetWindowLong( MyWindow, GWL_WNDPROC,
(DWORD)HookProc );

Sorry for above but right will be
WNDPROC OldProc=(WNDPROC)SetWindowLong( MyWindow, GWL_WNDPROC,
(DWORD)HookProc );
Avatar of andla

ASKER

Ok i suppose i will have to live with sending a PostMessage with WM_INITDIALOG when i create a button. I wish there where a way to freeze the messages. Hmm i was just thinking maybe i can catch them in the first loop:

while(GetMessages(msg,0,0,0))
{
}

Don't know.

/Andla
Then look for CWinApp::PreTranslateMessage
Avatar of andla

ASKER

Sorry once again i don't use MFC.
What would this be for a non MFC user ?

/Andreas
Avatar of andla

ASKER

C++ != MFC
then you must have own message loop.
place inside that loop
if (msg==WM_CREATE && create_struct->hwndParent==dialog_handle )
{
// use GetDlgCtrlID to get control ID and
if (id == nButtonID) {...}
}

also - you might hook WM_NCCREATE to get button handle.
And C++ != Windows Programming
;-)
Avatar of andla

ASKER

I will look into this later and se if can catch it. It's like catching a needle in a hay stack :-)

BTW I will try windows programming area in the future but if the response time is much longer I stick to the old gold mine.

/Andla
There are another way around your problem.
implement own button control (OCX, ActiveX) and place it insteed original button :)

As for me i'm rare guest in Windows Programming :)

WBR,
Petr.
Just a question:
what exectly do you need to do with your button? Why can't you do it in WM_CTLCOLORBTN?  
That would let you to create button with WM_CREATE?
And C++ != Windows Programming
;-)
Avatar of andla

ASKER

I don't recieve WM_CTLCOLORBTN or WM_CREATE. What i want to do i implementing a scripting engine that create different controls. I had working scripting call for WM_LBUTTONDOWN WM_LBUTTONUP and so on but it failed for WM_CREATE and therefore if i had creation code for buttons in WM_CREATE it was never called. Therefore i can live with posting a WM_INITDIALOG but it would be intresting to know new programming stuff to catch WM_CREATE. It is sad that i can't find any similar functions that you posted as MFC solutions that would work on simple Win32.

Regards
Andla
ASKER CERTIFIED SOLUTION
Avatar of kosolobov
kosolobov

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of andla

ASKER

Number 3 is intresting and number 1 if 3 doesn't work.
I think I have tested number 2:

while( GetMessage( &msg, NULL, 0, 0 )  )
{
     if(msg.message==WM_CTLCOLORBTN)
     {
          Sleep(0);//This is not recieved.
     }
     if(msg.message==WM_CREATE)
     {
          Sleep(0);//This is not recieved either.
     }
     if( IsDialogMessage( hWnd, &msg ) )
          continue;                
     TranslateMessage( &msg );  
     DispatchMessage( &msg );
}

Don't know if I can do number 2 if I first use number 3. If I use number 3 would that have a similar effect like:

OldProc=(HWND)SetWindowLong( MyWindow, GWL_WNDPROC,
(DWORD)HookProc );

but it would maybe listen to all new buttons created in the thread. Don't know I'm pretty new to number 3 approach.

Regards
Andla
2nd approach will not work for reason that GetMessage work only with Posted messages and WM_CREATE is Sended.
sorry about that :)

In 3d approach you can UnhookWindowsHook after receiving needed WM_CREATE.
Also this Hook will work for every SendMessage()in your application, sended by application itself as well by system.
Also try to use WM_NCCREATE in pp 3.

I done a test
1. generated with VC6.0 win32 "Hello World" project
2. and changed functions like:

HHOOK hHook;
LRESULT CALLBACK MyHookFunction(
  int nCode,      // hook code
  WPARAM wParam,  // current-process flag
  LPARAM lParam   // message data
)
{
     CWPSTRUCT* pcw = (CWPSTRUCT*)lParam;
     if (pcw->message == WM_CREATE && 
          ::GetDlgCtrlID(pcw->hwnd) == IDOK)
     {
          UnhookWindowsHookEx(hHook);
          MessageBox(NULL, "OK button created", "WM_CREATE", MB_OK);
          // more processing here
     }
     return CallNextHookEx(hHook, nCode, wParam, lParam);
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND     - process the application menu
//  WM_PAINT     - Paint the main window
//  WM_DESTROY     - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     int wmId, wmEvent;
     PAINTSTRUCT ps;
     HDC hdc;
     TCHAR szHello[MAX_LOADSTRING];
     LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

     switch (message)
     {
          case WM_COMMAND:
               wmId    = LOWORD(wParam);
               wmEvent = HIWORD(wParam);
               // Parse the menu selections:
               switch (wmId)
               {
                    case IDM_ABOUT:
// here
                         hHook = ::SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)MyHookFunction, NULL, ::GetCurrentThreadId());
                       DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
                       break;
                    case IDM_EXIT:
                       DestroyWindow(hWnd);
                       break;
                    default:
                       return DefWindowProc(hWnd, message, wParam, lParam);
               }
               break;
          case WM_PAINT:
               hdc = BeginPaint(hWnd, &ps);
               // TODO: Add any drawing code here...
               RECT rt;
               GetClientRect(hWnd, &rt);
               DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
               EndPaint(hWnd, &ps);
               break;
          case WM_DESTROY:
               PostQuitMessage(0);
               break;
          default:
               return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}
Avatar of andla

ASKER

This is maybe how MFC uses PreSubclassWindow ?
This looks intresting. Thanks for your help kosolobov.
I will maybe fall into further problem before i actually make this work. Stay put here if you want. Either way i appreciate your help.

Best regards
Andla
Thank you.
Waiting for your questions :)