GetWindow für Resourcen?



  • Hallo
    ich weiß nicht ob es schon oft gefragt wurde, aber in der FAQ steht nichts.

    Mich interessiert wie man einen Pointer zu einem Window aus der Resourcen bekommt.
    z.b. IDC_Edit1 also ein Edit-Feld.

    void CSite1::OnKillfocusPclients() 
    {
       CWnd wnd;
    
       UpdateData(TRUE);     // Feld ---> Var
       if (CSave::sbyMaxPlayer > m_byPClients) CSave::sbyPClients = m_byPClients;  //Checkt ob MaxPlayer 
       else																		   //höher als Privat Clients ist		
       {
           MessageBox ("Max Players must be higher than Privat Clients.","Error",MB_OK | MB_APPLMODAL | MB_ICONSTOP);
           m_byPClients = 0;
    	   UpdateData(FALSE);  //Var ---> Feld
    	   //wnd.GetWindow(IDC_PCLIENTS);   // Hier sollte ich dein Pointer bekommen
    	   //wnd.SetFocus();                // und hier sollte der Focus wieder auf das IDC_PCLIENTS gesetzt werden
       }
    

    Wenn ich das so laufen lasse stürtz das Programm ab. Deshalb hab ich es ausgeklammert. Hier heißt mein Edit-Fenster IDC_PCLIENTS.
    Kann mir einer helfen?



  • CWnd * pWnd = GetDlgItem(IDC_xxxxx);

    der zeiger is temporär (nur im aktuellen message-Handler gültig)



  • hm das funktioniert, also es gibt kein absturtz mehr, aber

    pWnd = SetFocus();

    scheints nicht richtig zu tun, denn der Focus, also der Cursor blinkt dann nicht auf dem Feld.



  • SetFocus kann nicht in einem OnSetFocus/OnKillFocus-Handler aufgerufen werden.

    Hilfsmessage mit PostMessage and den Dialog schicken, und dort dann SetFocus aufrufen



  • Gibt es irgendwo ein Tutorial für eigene Messages?
    Ich suche schon über 2 Stunden nach sowas, hab aber nichts brauchbares gefunden.

    Es geht von

    RegisterWindowMessage();

    bis

    #define WMU_EDIT WM_USER+5
    .
    .
    GetParent()->SendMessage(WMU_EDIT, GetDlgCtrlID(), (LPARAM)this);



  • RegisterWindowMessage ist notwendig, wenn du eindeutige messages zwischen verschiedenen Anwendungen / Modulen schicken willst.

    Ansosnten schreibt MSDN zu Windows Messages:

    Range Meaning
    0..WM_USER-1 Messages reserved for use by the system.
    WM_USER..0x7FFF Integer messages for use by private window classes.

    WM_APP through 0xBFFF Messages available for use by applications.
    ==> hier kannst du dich "bedienen" (aber aufpassen - s.u.)

    0xC000 through 0xFFFF String messages for use by applications. (i.e. die mot RegisterWindowMessage registrierten)

    Greater than 0xFFFF Reserved by the system for future use.

    .....

    Du kannst also z.B. eine Message mit

    #define UWM_MYDLG_SETCTLFOCUS  WM_APP  // LPARAM = HWND
    

    definieren

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/messagesandmessagequeues/messagesandmessagequeuesreference/messagesandmessagequeuesmessages/wm_user.asp



  • Hm, ich trau mich ja kaum noch zu fragen aber ich verstehe das nicht.

    void CSite1::OnKillfocusPclients() 
    {
       CWnd* wnd = GetDlgItem(IDC_PCLIENTS);
    
       UpdateData(TRUE);     // Feld ---> Var
       if (CSave::sbyMaxPlayer > m_byPClients) CSave::sbyPClients = m_byPClients;  //Checkt ob MaxPlayer 
       else																		   //höher als Privat Clients ist		
       {
           MessageBox ("Max Players must be higher than Privat Clients.","Error",MB_OK | MB_APPLMODAL | MB_ICONSTOP);
           m_byPClients = 0;
    	   UpdateData(FALSE);  //Var ---> Feld
    	   wnd.GetDlgItem(IDC_PCLIENTS);
    	   wnd->SendMessage(UWM_MYDLG_SETCTLFOCUS,0); 
       }
    

    was kommt vor SendMessage hin? wnd stimmt nicht. Welches Window?
    Ich hab ein Diolog in mit 3 CTabctrl Dialogen.
    Diesen Aufruf kommt von der 1. Registerkarte CSite1.

    Das steht in Site1.cpp -> ON_MESSAGE(UWM_MYDLG_SETCTLFOCUS,OnMYDLGSETCTFOCUS)
    bei der Message Map.

    Und das bei Site1.h -> afx_msg void OnMYDLGSETCTFOCUS();

    und dann noch die Funktion in Site1.cpp

    void CSite1::OnMYDLGSETCTFOCUS()
    {
    
    	CWnd* wnd = GetDlgItem(IDC_PCLIENTS);
        wnd = SetFocus();
    
    }
    

    Welches CWnd muß da rein damit es die Nachricht verschickt?



  • OK, war ein bißchen kurz 😉

    1. PostMessage statt SendMessage (das ist der eigentliche trick)
    2. nicht wnd->SendMessage sondern this-> (bzw. nix). Dorthin wird die Message geschickt

    Der Handler sollte

    afx_msg LRESULT memberFxn( WPARAM, LPARAM );
    

    deklariert sein

    ausfgühlicher:
    SendMessage wird "sofort" asgeführt, PostMessage stellt die Message nur in die Queue. Wir wollen den aktuellem handler zuerst vollständig durchlaufen lassen (damit der aktuelle Fokuswechsel "ferig" ist und nicht mit deinem SetFocus durcheinanderkommt) ==> also PostMessage

    Die Message geht am besten an das CSitel, welches auch die KillFocus-Notification-Handler hat. (Ich geh' mal davon aus, das CSitel auch von CWnd abgeleitet ist) - dessen PostMessage mußt du auch aufrufen

    Ich würde das HWND des zu fokussierenden Fensters gleich als Message-Parameter mitgeben (CWnd * geht leider nicht). Also, nach langer Vorrede:

    HWND hwndOfEdit = wndEdit->GetSafeHwnd(); 
    wnd->PostMessage(UWM_MYDLG_SETCTLFOCUS, 0, (LPARAM) hwndofEdit);
    

    und der Message-Handler dann:

    LRESULT CSitel::OnUwmXxxx(WPARAM wp, LPARAM lp)
    {
      ::SetFocus( (HWND) lp ); // globales (Win32)-SetFocus mit Window Handle aus lp aufrufen
      return(0);
    }
    

    Das ist zwar alles nicht so wunderschön MFC, aber die mag ich eh nicht so sehr 🙄



  • Geil es funktioniert, danke für deine Geduld. 😃
    Aber statt:

    wnd->PostMessage(UWM_MYDLG_SETCTLFOCUS, 0, (LPARAM) hwndofEdit);
    

    muß es:

    this->PostMessage(UWM_MYDLG_SETCTLFOCUS, 0, (LPARAM) hwndofEdit);
    

    heißen, wie du oben schon gesagt hast.

    Danke


Log in to reply