WINAPI интервейс программы

Тема в разделе "WASM.BEGINNERS", создана пользователем XshStasX, 8 июл 2010.

  1. XshStasX

    XshStasX New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2008
    Сообщения:
    991
    Делаю что-то типа не большой библиотеки классов(типа кнопки,списки и тп) для интерфейса...
    Столкнулся с такой не приятной штукой когда захотел обернуть основное окно в класс.
    А именно когда регистрируем класс( RegisterClassEx), требуется структура WNDCLASSEX и среди прочего нужен указатель на WNDPROC .
    Так как у меня класс то не все так просто(.
    Нужно как то указать дополнительный указатель чтоб вызвать из процедуру обработки сообщений окна из класса.

    Пока что вариант один:
    Так как WNDPROC всегда получает hwnd, то есть надежда что он всегда равен тому значению которое возвратила CreateWindow, и тем самым делать поиск нужного объекта и уже из него делать вызов...
    Может есть лучшее варианты ?

    Язык программирования С++.
     
  2. XshStasX

    XshStasX New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2008
    Сообщения:
    991
    Конечно это можно сделать через mfc, но не хотелось бы.
     
  3. XshStasX

    XshStasX New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2008
    Сообщения:
    991
    Просьба к модераторам удалить этот топик, так как только что пришол к выводу что mfc будет здесь более правильно.
     
  4. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    MFC наворочен до предела.
    Можно обойтись проще - см. код в следующем сообщении.
     
  5. letopisec

    letopisec New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    228
    XshStasX

    Сделай процедуру окна статической

    Свяжи указатель на экземпляр своего класса с хендлом созданного окна, через SetWindowLong. А впроцедуре окна получай этот указатель, через GetWindowLong.
     
  6. XshStasX

    XshStasX New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2008
    Сообщения:
    991
    В ней работает оператор this ? если да, как он туда передается??

    Не совсем уверен, пытаюсь сделать что - то типа плагинной системы к интерфейсу.
    [​IMG]
    После чего это может быть шаблоном для визуальной части программы.
     
  7. icew0rm

    icew0rm New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2010
    Сообщения:
    7
    Приветствую, XshStasX.

    Если тебе всё еще интересен вопрос, смотри код ниже. На вопрос "В ней работает оператор this ? если да, как он туда передается??" он отвечает.

    Оговорюсь сразу, этот код - всего лишь демонстрация, на что-то серьёзное не претендует.

    MFC навяжет тебе ЕГО правила построения кода. Тебе это надо? Напиши все сам и почувствуй себя богом :)

    Удачи!

    main.c
    Код (Text):
    1. #define UNICODE
    2.  
    3. #include <windows.h>
    4. #include "lib\gui\CWnd.h"
    5. #include "lib\gui\gui.h"
    6.  
    7. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR szCmdLine, int iCmdShow)
    8. {
    9.    CWnd wnd;
    10.    
    11.    wnd.Create(true);
    12.    ExitProcess(Gui_Cycle());
    13. }
    gui.h
    Код (Text):
    1. #pragma once
    2.  
    3. #define UNICODE
    4.  
    5. // Параметр обработчика события может быть NULL, или содержать
    6. // указатель на структуру с параметрами, характерными для
    7. // данного обработчика
    8. typedef void(*Gui_EVENTFUNC)(void*);
    9.  
    10. MSG Gui_MSG;
    11.  
    12. UINT Gui_Cycle(void)
    13. {
    14.    while(GetMessage(&Gui_MSG, 0, 0, 0))
    15.    {
    16.       TranslateMessage(&Gui_MSG);
    17.       DispatchMessage(&Gui_MSG);
    18.    }
    19.  
    20.    return Gui_MSG.wParam;
    21. }
    CWnd.h
    Код (Text):
    1. #pragma once
    2.  
    3. #define UNICODE
    4.  
    5. #include <windows.h>
    6. #include "gui.h"
    7.  
    8. class CWnd
    9. {
    10.    HWND  CWndHandle;
    11.    WNDCLASSEX CWndClassEx;
    12.    HINSTANCE CWndHInstance;
    13.    wchar_t* CWndClassName;
    14.    wchar_t* CWndTitle;
    15.  
    16.    static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    17.  
    18. public:
    19.  
    20.    CWnd();
    21.    void Create(boolean);
    22.    void Show();
    23.    void Hide();
    24.  
    25.    // Адреса функций-обработчиков событий
    26.    Gui_EVENTFUNC EventOnClick;
    27. };
    28.  
    29. typedef  CWnd* LPCWnd;
    30.  
    31.  
    32. CWnd :: CWnd()
    33. {
    34.    CWndClassName = L"CWnd";;
    35.    CWndTitle = L"Window";;
    36.    
    37.    CWndHInstance = GetModuleHandle(0);
    38.    
    39.    CWndClassEx.cbSize = sizeof(CWndClassEx);
    40.    CWndClassEx.style = CS_HREDRAW | CS_VREDRAW;
    41.    CWndClassEx.lpfnWndProc = WndProc;
    42.    CWndClassEx.cbClsExtra = 0;
    43.    CWndClassEx.cbWndExtra = 0;
    44.    CWndClassEx.hInstance =  CWndHInstance;
    45.    CWndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    46.    CWndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
    47.    CWndClassEx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    48.    CWndClassEx.lpszMenuName = 0;
    49.    CWndClassEx.lpszClassName =  CWndClassName;
    50.    CWndClassEx.hIconSm = 0;
    51.    
    52.    EventOnClick = NULL;
    53. }
    54.  
    55.  
    56. LRESULT CALLBACK CWnd :: WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
    57. {
    58.    HDC wnd_HDC;
    59.    RECT wnd_Rect;
    60.    PAINTSTRUCT wnd_PS;
    61.  
    62.    LPCWnd p_This = (LPCWnd)GetWindowLong(hwnd, GWL_USERDATA);
    63.  
    64.    switch(iMsg)
    65.    {
    66.       case WM_CREATE: break;
    67.       case WM_PAINT:
    68.          wnd_HDC = BeginPaint(hwnd, &wnd_PS);
    69.          GetClientRect(hwnd, &wnd_Rect);
    70.          DrawText(wnd_HDC, L"Hello, World!", -1, &wnd_Rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    71.          EndPaint(hwnd, &wnd_PS);
    72.          return 0;
    73.       case WM_DESTROY:
    74.          PostQuitMessage(0);
    75.          // DestroyWindow(hwnd);
    76.          return 0;
    77.    }
    78.    return DefWindowProc(hwnd, iMsg, wParam, lParam);
    79. }
    80.  
    81.  
    82. void CWnd :: Create(boolean ShowWindow)
    83. {
    84.    RegisterClassEx(&CWndClassEx);
    85.     CWndHandle = CreateWindow(CWndClassName, CWndTitle, WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, 0, 0,  CWndHInstance, 0);
    86.  
    87.    SetWindowLong(CWndHandle, GWL_USERDATA, (LONG)this);
    88.    if (ShowWindow) Show();
    89. }
    90.  
    91.  
    92. void CWnd :: Show()
    93. {
    94.    ShowWindow(CWndHandle, SW_SHOWNORMAL);
    95.    UpdateWindow(CWndHandle);
    96. }
    97.  
    98.  
    99. void CWnd :: Hide()
    100. {
    101.    ShowWindow(CWndHandle, SW_HIDE);
    102. }
     
  8. XshStasX

    XshStasX New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2008
    Сообщения:
    991
    icew0rm
    спс) я как раз тип такого и делаю ) сейчас все же mfc мне не понравился.
     
  9. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Код (Text):
    1. class TWindow
    2. {
    3.     private:
    4.         HWND m_Handle;
    5.  
    6.     public:
    7.         TWindow () { m_Handle = NULL; };
    8.         virtual ~TWindow () {};
    9.         //
    10.         // A single WNDPROC for all windows and for all classes
    11.         //
    12.         static LRESULT CALLBACK WndProc (HWND hWnd, UINT uiMsg, WPARAM wp, LPARAM lp)
    13.         {
    14.             //
    15.             // If 'this' already attached - then simply call
    16.             // virtual message map
    17.             //
    18.             TWindow* p = (TWindow*) ::GetWindowLong (hWnd, 0);
    19.             if (p) return p -> MsgMap (uiMsg, wp, lp);
    20.             //
    21.             // 'this' is not attached yet. Check if it should be attached.
    22.             //
    23.             if (uiMsg == WM_CREATE)
    24.             {
    25.                 p = ((TWindow**) lp) [0];
    26.                 p -> OnCreate (hWnd);
    27.                 return 0;
    28.             }
    29.             //
    30.             // No 'this' yet, so let Windows process all messages
    31.             // before WM_CREATE will be received.
    32.             //
    33.             return ::DefWindowProc (hWnd, uiMsg, wp, lp);
    34.         };
    35.         //
    36.         // May be overriden in a child classes to provide additional
    37.         // message handling, like painting and mouse response, etc.
    38.         // If overriden, child ALWAYS CALLS it in 'default' case.
    39.         //
    40.         virtual LRESULT MsgMap (UINT uiMsg, WPARAM wp, LPARAM lp)
    41.         {
    42.             if (uiMsg == WM_DESTROY) { OnDestroy (); return 0; }
    43.             return ::DefWindowProc (m_Handle, uiMsg, wp, lp);
    44.         };
    45.         //
    46.         // Child class MUST ALWAYS CALL this method BEFORE its own
    47.         // processing, because here HWND and 'this' are cross
    48.         // attached to each other.
    49.         //
    50.         virtual void OnCreate (HWND hWnd)
    51.         {
    52.             ::SetWindowLong (m_Handle=hWnd, 0, (LONG) this);
    53.         };
    54.         //
    55.         // Child class MUST ALWAYS CALL this method AFTER its own
    56.         // processing, because here HWND and 'this' are cross
    57.         // detached from each other.
    58.         //
    59.         virtual void OnDestroy ()
    60.         {
    61.             ::SetWindowLong (m_Handle, 0, 0);
    62.             m_Handle = NULL;
    63.         };
    64.         //
    65.         // If anything needs to be adjusted in WNDCLASS structure, then
    66.         // this method must be overriden in child class and different
    67.         // class name must be provided.
    68.         //
    69.         virtual LPCTSTR ProvideClassName () { return _T ("TWindow"); };
    70.         //
    71.         // Filling WNDCLASS structure.
    72.         // Child class MUST ALWAYS CALL this method BEFORE its own code.
    73.         //
    74.         virtual void RegisterMe (WNDCLASS& wc)
    75.         {
    76.             wc.lpfnWndProc = &TWindow::WndProc;
    77.             wc.cbWndExtra = sizeof (this);
    78.             wc.hInstance = ::GetModuleHandle (NULL);
    79.             wc.hCursor = ::LoadCursor (NULL, IDC_ARROW);
    80.             wc.lpszClassName = ProvideClassName ();
    81.         };
    82.         //
    83.         // Finally, creating a handle!
    84.         //
    85.         HWND CreateEx (
    86.             HWND hParent,
    87.             DWORD style,
    88.             DWORD xstyle,
    89.             LPCTSTR title,
    90.             int x, int y, int width, int height,
    91.             HMENU menu_or_child_ID)
    92.         {
    93.             WNDCLASS wc = {0};
    94.             RegisterMe (wc);
    95.             ::RegisterClass (&wc);
    96.  
    97.             return ::CreateWindowEx (
    98.                 xstyle,
    99.                 wc.lpszClassName,
    100.                 title,
    101.                 style,
    102.                 x, y, width, height,
    103.                 hParent,
    104.                 menu_or_child_ID,
    105.                 wc.hInstance,
    106.                 this);
    107.         };
    108. };
    109. //
    110. // Child class - main app window.
    111. //
    112. class TAppWindow : public TWindow
    113. {
    114.     public:
    115.         //
    116.         // Different name here will trigger the proper registration by Windows
    117.         //
    118.         virtual LPCTSTR ProvideClassName () { return _T ("TAppWindow"); };
    119.  
    120.         virtual void RegisterMe (WNDCLASS& wc)
    121.         {
    122.             //
    123.             // First ask base class to set it up
    124.             //
    125.             TWindow::RegisterMe (wc);
    126.             //
    127.             // Then adjust some properties just for this class
    128.             //
    129.             wc.hbrBackground = (HBRUSH) ::GetStockObject (LTGRAY_BRUSH);
    130.             wc.style = CS_VREDRAW | CS_HREDRAW;
    131.         };
    132.  
    133.         virtual void OnCreate (HWND hWnd)
    134.         {
    135.             //
    136.             // First ask base class to initialise
    137.             //
    138.             TWindow::OnCreate (hWnd);
    139.             //
    140.             // Then additional setup is done: creating child windows,
    141.             // loading data, configuration, etc.
    142.             //
    143.             //...
    144.         };
    145.  
    146.         virtual void OnDestroy ()
    147.         {
    148.             //
    149.             // First, do own code
    150.             //
    151.             ::PostQuitMessage (0);
    152.             //
    153.             // Then call base class to clean-up
    154.             //
    155.             TWindow::OnDestroy ();
    156.         };
    157. };