Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Запутался с WndProc...  (Прочитано 8674 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Topic
Интересующийся

ru
Offline Offline

« : 18-08-2010 09:13 » 

Проблема в следующем: у меня есть класс, отвечающий за создание/рисование окна.
Я хочу внести функцию обработки событий WndProc в мой класс.

Ошибка при компиляции указывает на строку:
Код:
KWnd mainWnd(TEXT("An application"), hInstance, nShowCmd, &KWnd::WndProc);

Текст ошибки:
Цитата
cannot convert parameter 4 from 'LRESULT (__stdcall KWnd::* )(HWND,UINT,WPARAM,LPARAM)' to 'LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM)'

Чего-то не соображу, как параметр привести к виду __stdcall KWnd::*
может это вообще не так делается?
Буду рад советам.

main.cpp
Код:
//#include <windows.h>
#include "KWnd.h"


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{

MSG msg;
KWnd mainWnd(TEXT("An application"), hInstance, nShowCmd, &KWnd::WndProc);

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}

KWnd.h
Код:
#include <windows.h>

void DrawNewPicture(HWND& hWnd,HDC& hMemDC,HBITMAP& hMemBMP);


class KWnd
{
public:
KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
LRESULT (WINAPI *pWndProc)(HWND, UINT, WPARAM, LPARAM),
LPCTSTR menuname = NULL,
int x = CW_USEDEFAULT, int y = 0,
int width = CW_USEDEFAULT, int height = 0,
UINT classStyle = CS_HREDRAW | CS_VREDRAW,
DWORD windowStyle = WS_OVERLAPPEDWINDOW,
HWND hParent = NULL);

// обработка сообщений: её в public или protected?
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


HWND GetHWnd() { return hWnd; }
protected:
HWND hWnd;
WNDCLASSEX wc;

};


KWnd::KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
   LRESULT (WINAPI *pWndProc)(HWND, UINT, WPARAM, LPARAM),
   LPCTSTR menuName, int x, int y, int width, int height,
   UINT classStyle, DWORD windowStyle, HWND hParent)
{
TCHAR szClassName[] = TEXT("KWndClass");

wc.cbSize = sizeof(wc);
wc.style = classStyle;
wc.lpfnWndProc = pWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszMenuName = menuName;
wc.lpszClassName = szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);


if (!RegisterClassEx(&wc))
{
TCHAR msg[100] = TEXT("Cannot register class: ");
wcscat_s(msg, 100, szClassName);
MessageBox(NULL, msg, TEXT("Error"), MB_OK | MB_ICONERROR);
return;
}

// по умолчанию окно располагается по центру
// и имеет фиксированную высоту/ширину
if (x == CW_USEDEFAULT && width == CW_USEDEFAULT)
{
// получаем разрешение монитора (1024х768)
int xFullScreen = GetSystemMetrics(SM_CXSCREEN);
int yFullScreen = GetSystemMetrics(SM_CYSCREEN);

// размеры окна по умолчанию
width  = 720;
height = 540;

// вычисляем позицию левого верхнего угла окна
x = int(xFullScreen/2 - width/2);
y = int(yFullScreen/2 - height/2);
}

hWnd = CreateWindow(szClassName, windowName, windowStyle,
x, y, width, height, hParent, (HMENU)NULL, hInst, NULL);

if (!hWnd)
{
TCHAR text[100] = TEXT("Cannot create window: ");
wcscat_s(text, 100, szClassName);
MessageBox(NULL, text, TEXT("Error"), MB_OK | MB_ICONERROR);
return;
}

ShowWindow(hWnd, cmdShow);
UpdateWindow(hWnd);
}

LRESULT CALLBACK KWnd::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HDC hMemDC=0;
static HBITMAP hMemBMP=0;
static bool bTimerOn=true;

// характеристики таймера
enum
{
e_timer_id=0, // идентификатор
e_timer_vl=10, // время в миллисекундах
};


switch(uMsg)
{
case WM_CREATE:
{
DrawNewPicture(hWnd,hMemDC,hMemBMP);
}
break;

case WM_TIMER:
{
DrawNewPicture(hWnd,hMemDC,hMemBMP);
}
break;

case WM_RBUTTONDOWN:
{
if(bTimerOn=!bTimerOn)
{
KillTimer(hWnd,e_timer_id);
}
else
{
SetTimer(hWnd,e_timer_id,e_timer_vl,0);
}
}
break;

case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;

HDC hDC = BeginPaint(hWnd, &ps);

GetClientRect(hWnd, &rect);

// Теперь копируем растр из памяти на экран
if(hMemDC && hMemBMP)
{
BitBlt(hDC, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY);
}
else
{
// отладочные команды (в случае ошибки)
// если hMemDC или hMemBMP пуст, то рисуем одну линию
// перечеркивающую экран
MoveToEx(hDC,rect.left,rect.top,0);
LineTo(hDC,rect.right,rect.bottom);
}

EndPaint(hWnd, &ps);
}
break;

case WM_LBUTTONDOWN:
{
DrawNewPicture(hWnd,hMemDC,hMemBMP);
}
break;

case WM_DESTROY:
{
if(hMemBMP)
{
DeleteObject(hMemBMP);
hMemBMP=0;
}

if(hMemDC)
{
DeleteDC(hMemDC);
hMemDC=0;
}

PostQuitMessage(0);
}
break;

default:
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
break;
}

return 0;
}

// Функция рисования на форме
// я её потом внесу в класс и уберу параметры, но это потом...
// пока и так работает
void DrawNewPicture(HWND& hWnd,HDC& hMemDC,HBITMAP& hMemBMP)
{
HPEN myPen = 0;
int xrand = 0;
int yrand = 0;
int Rrand = 0;
int Grand = 0;
int Brand = 0;
int iWidthRand = 0;
int iStyleRand = 0;

// послать в очередь сообщений сообщение WM_PAINT о том, что нужно перерисовать окно
InvalidateRect(hWnd,0,0);

// освободить память от предыдущего вызова
if(hMemBMP)
{
DeleteObject(hMemBMP);
hMemBMP = 0;
}

if(hMemDC)
{
DeleteDC(hMemDC);
hMemDC = 0;
}


RECT rect;
GetClientRect(hWnd, &rect);

{
HDC hDC = GetDC(hWnd);
hMemDC  = CreateCompatibleDC(hDC);
hMemBMP = CreateCompatibleBitmap(hDC,rect.right-rect.left+1,rect.bottom-rect.top+1);

// освободить память от предыдущего вызова
HBITMAP oldBMP = (HBITMAP)SelectObject(hMemDC,hMemBMP);
if (oldBMP) DeleteObject(oldBMP);

ReleaseDC(hWnd, hDC);
}


if(hMemDC && hMemBMP)
{
// рисуем что требуется
MoveToEx(hMemDC, 50, 60, NULL);

for (int i=0; i<10; i++)
{
// позиция по х и у, куда проводить линию
xrand = rand()%(rect.right-100)+50;
yrand = rand()%(rect.bottom-100)+50;

// стиль (начертание) линии
iStyleRand = rand()%7;

// толщина линии
iWidthRand = rand()%7;

// цвет линии
Rrand = rand()%256;
Grand = rand()%256;
Brand = rand()%256;

// создаем карандаш
myPen = CreatePen(iStyleRand, iWidthRand, RGB(Rrand, Grand, Brand));

// выбираем наш карандаш
SelectObject(hMemDC, myPen);

// нарисовать линию
LineTo(hMemDC, xrand, yrand);

// освобождаем память из под созданного карандаша
DeleteObject(myPen);
}
}
}


* MainWindow2.rar (2.33 Кб - загружено 838 раз.)
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #1 : 18-08-2010 10:14 » 

точно так так сделать нельзя, можно в функции обработки вызвать функцию класса.

1. Делаешь контейнер (мапу) в качестве ключа которой hwnd окна, а в качестве значения указатель на экземпляр класса, который будет обслуживать это окно.

2. При создании окна записываешь в мапу hwnd и поинтер на только что созданный обслуживающий класс.

3. Далее в 'LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM)' по hwnd ищешь нужный эксемпляр обслуживающего класса и вызываешь у него 'LRESULT (__stdcall KWnd::* )(HWND,UINT,WPARAM,LPARAM)', передавая ему все параметры статической функции и все!

НО лучше сначала использовать поиск по форуму и книгу по c++
« Последнее редактирование: 18-08-2010 10:24 от lapulya » Записан

С уважением Lapulya
VY
Новенький

ua
Offline Offline

« Ответ #2 : 18-10-2010 14:11 » 

1) KWnd::WndProc должна быть static
При этом в обработчике WM_CREATE в параметре CREATESTRUCT надо передать указатель на экземпляр класса KWnd

2) из выражения &KWnd::WndProc при создании окна убрать "&"
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #3 : 18-10-2010 14:24 » 

Этого мало, необходимо в оконной процедуре сопоставить экземпляр класса окна с дискриптором окна, поэтому нужно что-то вроде мапы или SetWindowLong, я предпочел мапу (поскольку такой объект уже был в менеджере окон) )))
« Последнее редактирование: 18-10-2010 14:26 от lapulya » Записан

С уважением Lapulya
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines