MessageBox



  • Ich habe mit HOOK eine MessageBox mit Ownerdraw Button.
    Nun möchte ich auf MouseHover und MouseLeave reagieren.
    Dazu habe ich versucht die Button zu subclassen.
    Das funktioniert aber nur mit IDYES und IDNO bei allen anderen Button ist danach der Button nicht mehr da.

    LRESULT CALLBACK CMessageBox::CustomMessageBoxProc(HWND hWnd, UINT uMsg, 
                                          WPARAM wParam, LPARAM lParam)
    {
    	switch(uMsg)
    	{
    	case WM_INITDIALOG:
        {
    		int Style;
    		Style = GetWindowLong(GetDlgItem(cmbv.hWnd,IDOK),GWL_STYLE);
    		Style |= BS_OWNERDRAW; 
    		SetWindowLong(GetDlgItem(cmbv.hWnd,IDOK),GWL_STYLE,(long)Style);
    		Style = GetWindowLong(GetDlgItem(cmbv.hWnd,IDYES),GWL_STYLE);
    		Style |= BS_OWNERDRAW; 
    		SetWindowLong(GetDlgItem(cmbv.hWnd,IDYES),GWL_STYLE,(long)Style);		
    		Style = GetWindowLong(GetDlgItem(cmbv.hWnd,IDNO),GWL_STYLE);
    		Style |= BS_OWNERDRAW; 
    		SetWindowLong(GetDlgItem(cmbv.hWnd,IDNO),GWL_STYLE,(long)Style);			
    		Style = GetWindowLong(GetDlgItem(cmbv.hWnd,IDABORT),GWL_STYLE);
    		Style |= BS_OWNERDRAW; 
    		SetWindowLong(GetDlgItem(cmbv.hWnd,IDABORT),GWL_STYLE,(long)Style);			
    		Style = GetWindowLong(GetDlgItem(cmbv.hWnd,IDCONTINUE),GWL_STYLE);
    		Style |= BS_OWNERDRAW; 
    		SetWindowLong(GetDlgItem(cmbv.hWnd,IDCONTINUE),GWL_STYLE,(long)Style);		
    		Style = GetWindowLong(GetDlgItem(cmbv.hWnd,IDIGNORE),GWL_STYLE);
    		Style |= BS_OWNERDRAW; 
    		SetWindowLong(GetDlgItem(cmbv.hWnd,IDIGNORE),GWL_STYLE,(long)Style);	
    		Style = GetWindowLong(GetDlgItem(cmbv.hWnd,IDRETRY),GWL_STYLE);
    		Style |= BS_OWNERDRAW; 
    		SetWindowLong(GetDlgItem(cmbv.hWnd,IDRETRY),GWL_STYLE,(long)Style);	
     		Style = GetWindowLong(GetDlgItem(cmbv.hWnd,IDTRYAGAIN),GWL_STYLE);
    		Style |= BS_OWNERDRAW; 
    		SetWindowLong(GetDlgItem(cmbv.hWnd,IDTRYAGAIN),GWL_STYLE,(long)Style);	  
    		Style = GetWindowLong(GetDlgItem(cmbv.hWnd,IDCANCEL),GWL_STYLE);
    		Style |= BS_OWNERDRAW; 
    		SetWindowLong(GetDlgItem(cmbv.hWnd,IDCANCEL),GWL_STYLE,(long)Style);		
    
    		//if(GetDlgItem(cmbv.hWnd,IDOK));
    		//	old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDOK),GWL_WNDPROC,(long)BUTTONPROC);
    		//if(GetDlgItem(cmbv.hWnd,IDABORT));
    		//	old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDABORT),GWL_WNDPROC,(long)BUTTONPROC);
    		//if(GetDlgItem(cmbv.hWnd,IDCANCEL));
    		//	old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDCANCEL),GWL_WNDPROC,(long)BUTTONPROC);		
    		//if(GetDlgItem(cmbv.hWnd,IDCONTINUE));
    		//	old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDCONTINUE),GWL_WNDPROC,(long)BUTTONPROC);
    		//if(GetDlgItem(cmbv.hWnd,IDIGNORE));
    		//	old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDIGNORE),GWL_WNDPROC,(long)BUTTONPROC);			
    		if(GetDlgItem(cmbv.hWnd,IDNO));
    			old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDNO),GWL_WNDPROC,(long)BUTTONPROC);
    		//if(GetDlgItem(cmbv.hWnd,IDRETRY));
    		//	old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDRETRY),GWL_WNDPROC,(long)BUTTONPROC);
    		//if(GetDlgItem(cmbv.hWnd,IDTRYAGAIN));
    		//	old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDTRYAGAIN),GWL_WNDPROC,(long)BUTTONPROC);			
    		if(GetDlgItem(cmbv.hWnd,IDYES));
    			old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDYES),GWL_WNDPROC,(long)BUTTONPROC);
    

    woran liegt das?

    Die Button die nicht mehr da sind sind auskommentiert. 🙄



  • papa_multi schrieb:

    ...		
    //if(GetDlgItem(cmbv.hWnd,IDOK));
    //	old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDOK),GWL_WNDPROC,(long)BUTTONPROC);
    ...
    

    woran liegt das?

    Die Button die nicht mehr da sind sind auskommentiert. 🙄

    GWL_WNDPROC Sets a new address for the window procedure.

    Wie sieht denn die eigene BUTTONPROC aus ?



  • LRESULT CALLBACK CMessageBox::BUTTONPROC(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	static bool g_bMouseTrack=false;
    	switch(uMsg)
    	{
    	case WM_MOUSEMOVE:
    	{
    		if(!g_bMouseTrack)
    		{
    			TRACKMOUSEEVENT tme = {0};
    			DWORD dwPos = GetMessagePos();
    			POINTS pts = MAKEPOINTS(dwPos);
    			tme.cbSize = sizeof(TRACKMOUSEEVENT);
    			tme.dwFlags = TME_HOVER | TME_LEAVE;
    			tme.hwndTrack = hWnd;
    			tme.dwHoverTime = 200;//HOVER_DEFAULT;
    
    			g_bMouseTrack = TrackMouseEvent(&tme);
    		}
    
    		break;
    	}
    
    	case WM_MOUSELEAVE:
    	{
    		g_bMouseTrack = FALSE;
    		HWND s = GetFocus();
    		if(hWnd==s)
    			return 0;
    		HDC dc = GetDC(hWnd);
    		HBRUSH hbr = CreateSolidBrush(RGB(225,233,248));
    		RECT rect,rect1;
    		GetClientRect(hWnd,&rect);
    		InflateRect(&rect,-3,-3);
    		FrameRect(dc,&rect,hbr);
    		InflateRect(&rect,-1,-1);
    		DeleteObject(hbr);
    
    	}	
    
    		return 0;
    
    	case WM_MOUSEHOVER:
    	{
    		HDC dc = GetDC(hWnd);
    		HBRUSH hbr = CreateSolidBrush(RGB(255,199,60));
    		RECT rect,rect1;
    		GetClientRect(hWnd,&rect);
    
    		InflateRect(&rect,-3,-3);
    		FrameRect(dc,&rect,hbr);
    		InflateRect(&rect,-1,-1);
    		DeleteObject(hbr);
    
    		return 0;
    	}
    
    	case WM_KILLFOCUS:
    		g_bMouseTrack = FALSE;
    		break;
       }
       return (CallWindowProc(old,hWnd,uMsg,wParam,lParam));
    }
    


  • Wäre es nicht viel einfacher einen eigenen Dialog zu erstellen?



  • Nein, es ist eine Herausforderung die MessageBox auszutricksen.

    Das meiste geht ja schon, halt nur MouseHover nicht.

    Wir sind doch hier im WinApi-Forum 😕



  • Intersse ist da siehe.

    Siehe gelesen steht schon bei 194.

    Keiner eine Idee?? Warum nur IDYES und IDOK laufen.

    Bs_Ownerdraw futzt doch auch....



  • Irgendwie scheinst du dieses Forum mit einer Servicehotline zu verwechseln.
    Teste mal alle Funktionen auf Fehler, also jeweils die Rückgabewerte und GetLastError überprüfen.



  • 1. Wenn man Beakpoints in den Callback setzt werden diese angesprungen ?

    2. In der Hilfe zu WM_MOUSEHOVER findet sich:

    Remarks
    Hover tracking stops when WM_MOUSEHOVER is generated. The application must call TrackMouseEvent again if it requires further tracking of mouse hover behavior.

    Der Systemcall TrackMouseEvent() ist im code nur bei WM_MOUSEMOVE zu sehen.
    Kann es sein das dieser dort nicht reicht ?



  • nwp3 schrieb:

    Irgendwie scheinst du dieses Forum mit einer Servicehotline zu verwechseln.

    Das Forum ist zwar keine Servicehotline, aber viele Augen sehen mehr.

    Das Problem ist gelöst GetLastError() ist dein und mein Freund wenn es nicht weiter geht.

    Windows, die keinen HWND-Wert haben gibt es nicht und diese sollte man auch nicht subclassen.

    Es kommt dann zu solch unnetten Seiteneffekten.

    Lösung:

    if(GetDlgItem(cmbv.hWnd,IDOK)//Abfrage ob der Button in der MessageBox angezeigt wird
      old = (WNDPROC)SetWindowLong(GetDlgItem(cmbv.hWnd,IDOK),GWL_WNDPROC,(long)BUTTONPROC);
    

  • Mod

    Um eine Messagebox zu subclassen benutzte ich einen WH_CBT Hook.



  • Martin Richter schrieb:

    Um eine Messagebox zu subclassen benutzte ich einen WH_CBT Hook.

    Den WH_CBT HOOK habe ich. Mein Subclassing läuft innerhalb der HOOK.

    Wie kann man damit WM_MOUSEHOVER, WM_MOUSELEAVE der Button(IDOK, IDYES, IDNO ...) verarbeiten?

    Ich bin lernbereit und nehme Anregungen gern an.



  • Martin Richter schrieb:

    Um eine Messagebox zu subclassen benutzte ich einen WH_CBT Hook.

    Ist IMO am einfachsten! 👍


Anmelden zum Antworten