Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 651
  • Last Modified:

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.
0
andla
Asked:
andla
  • 11
  • 8
  • 2
  • +2
1 Solution
 
jkrCommented:
Beg my pardon, but a button is not a dialog at all - so how is it supposed to receive that message?
0
 
jkrCommented:
Ooops, "Beg my pardon" should of course be "Beg your pardon" .o)
0
 
GGRUNDYCommented:
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.)
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
andlaAuthor Commented:
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
0
 
mblatCommented:
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.
0
 
kosolobovCommented:
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 );

0
 
kosolobovCommented:
Sorry for above but right will be
WNDPROC OldProc=(WNDPROC)SetWindowLong( MyWindow, GWL_WNDPROC,
(DWORD)HookProc );
0
 
andlaAuthor Commented:
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
0
 
kosolobovCommented:
Then look for CWinApp::PreTranslateMessage
0
 
andlaAuthor Commented:
Sorry once again i don't use MFC.
What would this be for a non MFC user ?

/Andreas
0
 
andlaAuthor Commented:
C++ != MFC
0
 
kosolobovCommented:
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.
0
 
kosolobovCommented:
And C++ != Windows Programming
;-)
0
 
andlaAuthor Commented:
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
0
 
kosolobovCommented:
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.
0
 
mblatCommented:
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?
0
 
kosolobovCommented:
And C++ != Windows Programming
;-)
0
 
andlaAuthor Commented:
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
0
 
kosolobovCommented:
1. The best way, in my opinion, is to create custom control(ActiveX) which will subclass button control and place it on dialog.

2. Another way is to insert in you plain Win32 application message loop several lines of code:

BOOL bRet;
MSG msg;
while( (bRet = ::GetMessage( &msg, NULL, 0, 0 )) != 0)
{
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
// hear you can intercept WM_CREATE for dialog controls
if (msg.message == WM_CREATE)
{
CREATESTRUCT* pcs = (CREATESTRUCT*)msg.lParam;
if (pcs->hwndParent == hMyDialog && ::GetDlgCtrlID(msg.hwnd) == MY_BUTTON_ID)
{
// handle your button WM_CREATE here
}
}
// process standard handler
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }
}

3. the last one is to hook apllication message loop, like:
HHOOK hHook = ::SetWindowsHookEx(WH_CALLWNDPROC, MyHookFunction, NULL, ::GetCurrentThreadId());
And process in MyHookFunction WM_CREATE message exactly like in method 2.

I suppose this will be  enough. :)
0
 
andlaAuthor Commented:
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
0
 
kosolobovCommented:
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.

0
 
kosolobovCommented:
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;
}
0
 
andlaAuthor Commented:
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
0
 
kosolobovCommented:
Thank you.
Waiting for your questions :)
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 11
  • 8
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now