Новичок
Профиль
Группа: Участник
Сообщений: 13
Регистрация: 20.12.2010
Репутация: нет Всего: нет
|
Добрый день. Пытаюсь построить простенькую классовую оболочку для WinAPI (т.е. крайне простенький аналог MFC), но никак не могу разобраться с проблемой. Для простоты пока попытка реализовать без MDI. Интерфейс базового класса окна (файл KWnd.h): Код | #include <Windows.h>
class KWnd { virtual void OnDraw(HDC hDC) {} virtual void OnKeyDown(WPARAM wParam, LPARAM lParam) {} virtual LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); bool RegClass(LPCTSTR lpszClass, LPCSTR lpszMenuName, HINSTANCE hInst, UINT classStyle); static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); public: HWND m_hWnd; KWnd() { m_hWnd = NULL; } virtual ~KWnd() {}
virtual bool CreateEx(DWORD dwExStyle, LPCTSTR lpszClass, LPCTSTR lpszName, UINT classStyle, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hParent, LPCSTR lpszMenuName, HINSTANCE hInst); virtual WPARAM MessageLoop(void); BOOL ShowWindow(int nCmdShow) const { return ::ShowWindow(m_hWnd, nCmdShow); } BOOL UpdateWindow() const { return ::UpdateWindow(m_hWnd); } };
|
Реализация методов (файл KWnd.cpp): Код | #include "KWnd.h" LRESULT KWnd::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_KEYDOWN: OnKeyDown(wParam, lParam); return 0; case WM_PAINT: { PAINTSTRUCT ps;
BeginPaint(m_hWnd, &ps); OnDraw(ps.hdc); EndPaint(m_hWnd, &ps); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } }
LRESULT CALLBACK KWnd::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { KWnd *pWnd = 0; if ( uMsg == WM_NCCREATE ) { if ( IsBadReadPtr((void*) lParam, sizeof(CREATESTRUCT)) ) // проверка, имеет ли процесс право чтения указанного региона памяти MessageBox(NULL, "The lParam for new window does not have read access to all bytes.", "Error", MB_OK | MB_ICONSTOP); pWnd = (KWnd *)(((LPCREATESTRUCT)lParam)->lpCreateParams); if ( IsBadReadPtr(pWnd, sizeof(KWnd))) MessageBox(NULL, "The pointer to new window does not have read access to all bytes.", "Error", MB_OK | MB_ICONSTOP); SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)(pWnd)); } else pWnd = (KWnd *)(GetWindowLongPtr(hWnd, GWL_USERDATA)); if ( pWnd ) return pWnd -> WndProc(hWnd, uMsg, wParam, lParam); else return DefWindowProc(hWnd, uMsg, wParam, lParam); }
bool KWnd::RegClass(LPCTSTR lpszClass, LPCSTR lpszMenuName, HINSTANCE hInst, UINT classStyle) { WNDCLASSEX wc; if( !GetClassInfoEx(hInst, lpszClass, &wc) ) { wc.cbSize = sizeof(wc); wc.lpfnWndProc = StaticWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = NULL; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH); wc.lpszMenuName = lpszMenuName; wc.lpszClassName = NULL; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wc.hInstance = hInst; wc.lpszClassName = lpszClass; wc.style = classStyle;
if( !RegisterClassEx(&wc) ) { char msg[100] = "Cannot register class: "; strcat(msg, lpszClass); MessageBox(NULL, msg, "Error", MB_OK | MB_ICONSTOP); return false; } } return true; }
bool KWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClass, LPCTSTR lpszName, UINT classStyle, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hParent, LPCSTR lpszMenuName, HINSTANCE hInst) { if ( !RegClass(lpszClass, lpszMenuName, hInst, classStyle) ) return false;
m_hWnd = CreateWindowEx(dwExStyle, lpszClass, lpszName, dwStyle, x, y, nWidth, nHeight, hParent, (HMENU)NULL, hInst, NULL); if(!m_hWnd) MessageBox(NULL, "Cannot create main window", "Error",MB_OK); return m_hWnd != NULL; }
WPARAM KWnd::MessageLoop() { MSG msg;
while ( GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
|
На базе этого класса создается класс основного окна приложения: Код | #include <Windows.h> #include "KWnd.h"
class MainWindow : public KWnd { RECT rect;
void OnKetDown(WPARAM wParam, LPARAM lParam ); void OnDraw(HDC hDC);
// процедура для диалогового окна о создании нового изображения //static BOOL DlgNewProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static BOOL CALLBACK StaticDlgNewProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); public: MainWindow() { m_hWnd = NULL; } };
// реализация методов void MainWindow::OnKetDown(WPARAM wParam, LPARAM lParam ) { switch(wParam) { case VK_ESCAPE: SendMessage(m_hWnd, WM_CLOSE, 0, 0); break; } } void MainWindow::OnDraw(HDC hDC) { // тестовый вывод GetClientRect (m_hWnd, &rect); DrawText(hDC, "Некий текст.", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); SetPixel(hDC, 50, 50, RGB(255,0,0)); }
LRESULT MainWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); OnDraw(ps.hdc); EndPaint(hWnd, &ps); break; } case WM_COMMAND: switch(LOWORD(wParam)) { case ID_EXIT: SendMessage(hWnd, WM_CLOSE, 0, 0); break; default: break; } InvalidateRect(hWnd, NULL, TRUE); break; case WM_CLOSE: if (IDYES == MessageBox(hWnd, "Точно закрыть приложение?", "", MB_YESNO | MB_ICONQUESTION)) DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; }
|
Основная функция программы: Код | int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { MainWindow MainWnd; MainWnd.CreateEx(0, "MainWnd","Основное окно", CS_HREDRAW | CS_VREDRAW, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInst); MainWnd.ShowWindow(nCmdShow); MainWnd.UpdateWindow(); return MainWnd.MessageLoop(); }
|
А теперь к проблеме. При попытке запуска всего этого возникает сообщение из строки 35 второго куска кода (статический метод базового класса), вследствие чего окно худо бедно создается, но ненормальное — в нем ничего не рисуется функцией OnDraw(...), а когда закрываешь с помощью крестика выполнение программы не прекращается (и соответственно сообщения о закрытии тоже нет, т.к. не обрабатываются события). В чем может быть проблема? P.S. Сразу замечу, что если использовать MDI, то главное окно функционирует должным образом, но я не хочу лезть в разбирательства еще и с этим MDI, поэтому хотелось бы без этого. Модификация с MDI заключается в следующем: содержимое функции StaticWndProc заменяется на: Код | LRESULT CALLBACK KWnd::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { KWnd *pWnd = 0; if ( uMsg == WM_NCCREATE ) { if ( IsBadReadPtr((void*) lParam, sizeof(CREATESTRUCT)) ) // проверка, имеет ли процесс право чтения указанного региона памяти MessageBox(NULL, "The lParam for new window does not have read access to all bytes.", "Error", MB_OK | MB_ICONSTOP); MDICREATESTRUCT * pMDIC = (MDICREATESTRUCT *) ((LPCREATESTRUCT) lParam) -> lpCreateParams; pWnd = (KWnd *) (pMDIC -> lParam); if ( IsBadReadPtr(pWnd, sizeof(KWnd))) MessageBox(NULL, "The pointer to new window does not have read access to all bytes.", "Error", MB_OK | MB_ICONSTOP); SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)(pWnd)); } else pWnd = (KWnd *)(GetWindowLongPtr(hWnd, GWL_USERDATA)); if ( pWnd ) return pWnd -> WndProc(hWnd, uMsg, wParam, lParam); else return DefWindowProc(hWnd, uMsg, wParam, lParam); }
|
А содержимое функции создания окна CreateEx заменяется на: Код | bool KWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClass, LPCTSTR lpszName, UINT classStyle, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hParent, LPCSTR lpszMenuName, HINSTANCE hInst) { if ( !RegClass(lpszClass, lpszMenuName, hInst, classStyle) ) return false;
MDICREATESTRUCT mdic; memset(&mdic, 0, sizeof(mdic)); mdic.lParam = (LPARAM) this; m_hWnd = CreateWindowEx(dwExStyle, lpszClass, lpszName, dwStyle, x, y, nWidth, nHeight, hParent, (HMENU)NULL, hInst, &mdic); if(!m_hWnd) MessageBox(NULL, "Cannot create main window", "Error",MB_OK); return m_hWnd != NULL; }
|
Вследствие чего полагаю, что проблемы именно в базовом классе с этими двумя функциями... Может, не вижу какой-то мелочи? Это сообщение отредактировал(а) nobody0 - 8.8.2012, 09:40
|