Объектно-ориентированный c ++ win32? - PullRequest
8 голосов
/ 01 августа 2010

Я хочу создать свой собственный класс для обработки окон и процедуры окна, но я заметил, что процедура окна должна быть статической! Теперь мне интересно, можно ли сделать объектную процедуру окна ориентированной? Я читал некоторые учебные пособия по объектно-ориентированным окнам, но они всегда делают процедуру статической -.- какая польза в этом? : /

Буду признателен за любые ссылки или информацию о том, как обойти эту проблему,

спасибо

Ответы [ 5 ]

11 голосов
/ 01 августа 2010

Вы можете обойти это, заставив статический WndProc делегировать все членам:

// Forward declarations
class MyWindowClass;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

std::map<HWND, MyWindowClass *> windowMap;

// Your class
class MyWindowClass  {
private:
  HWND m_handle;

  // The member WndProc
  LRESULT MyWndProc(UINT message, WPARAM wParam, LPARAM lParam) { /* ... */ }

public:
  MyWindowClass()
  {
    /* TODO: Create the window here and assign its handle to m_handle */
    /* Pass &WndProc as the pointer to the Window procedure */

    // Register the window
    windowMap[m_handle] = this;
  }
};

// The delegating WndProc
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  std::map<HWND, MyWindowClass *>::iterator it = windowMap.find(hWnd);
  if (it != windowMap.end())
    return it->second->MyWndProc(message, wParam, lParam);
  return 0;
}
6 голосов
/ 01 августа 2010

Общий способ разрешения представления окна в качестве экземпляра класса состоит в том, чтобы использовать SetWindowLongPtr и GetWindowLongPtr, чтобы связать указатель экземпляра класса с дескриптором окна. Ниже приведен пример кода, с которого можно начать. Может не скомпилироваться без нескольких настроек. Это только для справки.

Лично я прекратил откатывать свои собственные классы окон несколько лет назад, когда обнаружил шаблонные классы ATW CWindow и CWindowImpl. Они позаботятся о выполнении всего этого мирского кодирования для вас, поэтому могут сосредоточиться только на написании методов, которые обрабатывают оконные сообщения. Посмотрите пример кода, который я написал здесь .

Надеюсь, это поможет.

class CYourWindowClass
{
private:
    HWND m_hwnd;

public:
    LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
            case WM_CREATE: return OnCreate(wParam, lParam);
            case wM_PAINT: return OnPaint(wParam, lParam);
            case WM_DESTROY:
            {
                SetWindowLongPtr(m_hwnd, GWLP_USERDATA, NULL);
                m_hwnd = NULL;
                return 0;
            }
        }
        return DefWindowProc(m_hwnd, uMsg, wParam, lParam);

    }

    CYourWindowClass()
    {
        m_hwnd = NULL;
    }

    ~CYourWindowClass()
    {
        ASSERT(m_hwnd == NULL && "You forgot to destroy your window!");
        if (m_hwnd)
        {
            SetWindowLong(m_hwnd, GWLP_USERDATA, 0);
        }
    }

    bool Create(...) // add whatever parameters you want
    {
        HWND hwnd = CreateWindow("Your Window Class Name", "Your Window title", dwStyle, x, y, width, height, NULL, hMenu, g_hInstance, (LPARAM)this);
        if (hwnd == NULL)
            return false;

        ASSERT(m_hwnd == hwnd);
        return true;
    }


    static LRESULT __stdcall StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        CYourWindowClass* pWindow = (CYourWindowClass*)GetWindowLongPtr(hwnd, GWLP_USERDATA);

        if (uMsg == WM_CREATE)
        {
            pWindow = ((CREATESTRUCT*)lParam)->lpCreateParams;
            SetWindowLongPtr(hwnd, GWLP_USERDATA, (void*)pWindow);
            m_hWnd = hwnd;
        }

        if (pWindow != NULL)
        {
            return pWindow->WndProc(uMsg, wParam, lParam);
        }

        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    };


};
3 голосов
/ 01 августа 2010

Если вы ищете объектно-ориентированный Win32 API, вам следует обратиться к MFC и / или WTL .

2 голосов
/ 15 января 2011

Просто чтобы добавить ответ Брайана, но для среды win32, более удобной для начинающих, взгляните на Win32 ++ .Сама библиотека не так полна по своим возможностям по сравнению с MFC или QT, но это компромисс, который разработчик сделал в начале, чтобы библиотека была простой для понимания и простой в использовании.в этой теме я настоятельно рекомендую вам взглянуть на него, поскольку он использует еще одну технику для сохранения указателя 'this' с помощью локального хранилища потоков.

1 голос
/ 01 августа 2010

Вы можете использовать дескриптор окна, переданный WindowProc, чтобы захватить объект, который вы создали для этого конкретного окна, и делегировать обработку события этому объекту.

, например

IMyWindowInterface* pWnd = getMyWindowObject(hWnd);
pWnd->ProcessMessage(uMsg, wParam, lParam);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...