[WinAPI] Cum suprascriu functia fereastra (dialog)?

Folosire Windows API in programe C/C++ (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[WinAPI] Cum suprascriu functia fereastra (dialog)?

Post by Ovidiu Cucu » 27 May 2008, 14:29

Problema
Sa zicem ca as vrea sa fac un mic wrapper peste Windows API care are la baza o clasa, sa-i zicem CBaseDialog. Se vrea doar folosirea de functii virtuale pentru handlere (macar pentru mesajele cele mai folosite, cum ar fi WM_COMMAND, WM_NOTIFY, etc) si nu sunt permise macro-uri. La prima vedere, problema e simpla dar... exista un "dar": procedura callback a ferestrei (dialogului) nu poate fi facuta membru altfel decat daca o declar static. Deci nu poate fi virtuala si in plus nu pot apela din interiorul ei functii nestatice (cum ar fi functiile handler OnCommand, OnNotify, etc).

(O posibila) rezolvare
Ar fi de incercat mai multe metode printre care sa se adauge intr-un std::map perechi window handle - pointer la obiect. Cand se intra in procedura ferestrei, avand HWND-ul, caut in map pointerul corespunzator si prin intermediul sau apelez o metoda non-statica din clasa respectiva.
Mai simplu, mai aproape de WinAPI programming si fara a mai amesteca STL-ul sau alte biblioteci, este sa folosesc asazisele Window Properties.

Exemplu

Code: Select all

 // a base class that encapsulates a dialog box.
class BASEDIALOG_EXP CBaseDialog : public CBaseWindow
{
// ....
// Operations:
public:
    INT_PTR DoModal(HINSTANCE hInstance, UINT nResourceID, HWND hWndParent = NULL);
// Overrides
protected:
    // Dialog procedure
    virtual BOOL DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    // Message handlers
    virtual BOOL OnCommand(UINT nNotifyCode, UINT id, HWND hWndCtl);
    //  ...etc...
// Implementation
protected:
    // Static callback dialog procedure
    static BOOL CALLBACK CallbackDialogProc(HWND hWnd, UINT uMsg, 
                                            WPARAM wParam, LPARAM lParam);
};

Code: Select all

// A function that creates a modal dialog (just as an example).
INT_PTR CBaseDialog::DoModal(HINSTANCE hInstance, UINT nResourceID, HWND hWndParent)
{
    // A pointer to actual object (may be of a derived type) 
    // is sent through lParam parameter of DialogBoxParam function.
    // This will be found in the dialog procedure when receiving WM_INITDIALOG message.  
    return ::DialogBoxParam(hInstance, 
                            MAKEINTRESOURCE(nResourceID), hWndParent, 
                            CBaseDialog::CallbackDialogProc,
                            (LPARAM)this);
}

Code: Select all

// The (static) callback dialog procedure
BOOL CALLBACK CBaseDialog::CallbackDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if(WM_INITDIALOG == uMsg)
    {
        // The pointer to the actual object sent with lParam of WM_INITDIALOG 
        CBaseDialog* pDlg = (CBaseDialog*)lParam;
        ::SetProp(hWnd, CBaseWindow::m_pszObjPtrPropName, pDlg); // set the window property
    }
    // get the window property
    CBaseDialog* pDlg = (CBaseDialog*)::GetProp(hWnd, CBaseWindow::m_pszObjPtrPropName);
    if(NULL == pDlg)
    {
        // property is not yet set, so return
        return 0; // unhandled
    }
    return pDlg->DialogProc(hWnd, uMsg, wParam, lParam); // call non-static member function
}

Code: Select all

// Finally, the virtual member "dialog procedure"
BOOL CBaseDialog::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    BOOL bHandled = FALSE;
    switch(uMsg)
    {
    case WM_COMMAND:
        bHandled = OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
        break;
    // ...etc, etc...
    }
    return bHandled;
}

<< Back to Windows API Index



Post Reply