WinAPI
Там никаких сообщений, разве что WM_TIMER и WM_PAINT. Я бы на твоём месте написал это под MFC, если ничего большего, чем двигать прямоугольник не требуется.
нет. это нужно только на апи сделать
вообще-то если нужно только прямоугольник двигать, то MFC на х. не нужен, лучше Win32 project там все прозрачно два case'а на два сообщения и привет, а MFC у человека по первому впечатлению вызывает рвотную реакцию... но вероятно эти два сообщения и будут необходимыми и достаточными.
вот пример:
case WM_TIMER:
if (f==1)
{
InvalidateRect(hwnd,NULL,1);
if (x>maxX) x=0;
else x+=dx;
}
break;
case WM_PAINT:
hdc=BeginPaint(hwnd,&paintstruct);
Rectangle(hdc,x-BOX_LENGTH,y-BOX_WIDTH,x+BOX_LENGTH,y+BOX_WIDTH);
//BitBlt(hdc,0,0,maxX,maxY, memdc,0,0,SRCCOPY);
EndPaint(hwnd,&paintstruct);
break;
ты таймер то включил ? тчо от него сообщений ждешь ?
Маза таймер завести предварительно SetTimer'ом
из меня устанавливаем флаг=1 и после этого должен начать рисовать
как рисовать?
создаем виртуальное окно и в него рисуеи. но сейчас после выполнения программы ничего нет...
нужно ли виртуальное окно и из него обновлять контекст. или нет?
окно то само есть ?
в wm_timer рисуешь в виртуальное окно и вызываешь инвалидейт, а в паинт просто битблт виртуального на реальное окно ...
А это как-то по-другому делаться может?
на вопрос по другому: можно сразу рисовать в окно без BitBlt...
( возможно прямоугольник твой вне видимоя части, если все остально в порядке ).
Можно конечно и без memdc, но тогда если на картинке есть статические обьекты (например стенка) то каждый раз надо будет рисовать заново. Плюс при стирании предыдущей,используя PatBlt, будет мигание....
ну как... нифина не получается
Ты цвета правильные выбрал (видные )? FillMode еще или чего там?..
еще самая очевидная ошибка : создавая CompatibleDC не забудь в него выбрать нормальную битмапу, а то она от рождения : 1х1 ЧБ !
Попросите у человека полный проект.
Сдаётся мне, что на МФЦ я это сделаю на порядок быстрее, чем кто-то на ВИНАПИ. Хотя, тут надо именно на ВИНАПИ.
в wm_timer рисуешь в виртуальное окно и вызываешь инвалидейт, а в паинт просто битблт виртуального на реальное окно ...
С буффером действительно лучше, чтоб не мигало, но можно в принципе это все на PAINT поставить и заполнение буффера, и flush.
Ладно, вопрос не в этом, написанный код тоже должен по идее работать!..
Не сцать, щас сделаю на WINAPI, -- у меня свой MFC есть
LRESULT CALLBACK WindowFunc(HWND hwnd,UINT message,
WPARAM wParam,LPARAM lParam)
{
HDC hdc;
int x, y, dx,dy;
PAINTSTRUCT paintstruct;
switch (message)
{
case WM_CREATE:
maxX = GetSystemMetrics (SM_CXSCREEN);
maxY = GetSystemMetrics (SM_CYSCREEN);
x_c=maxX/2
y_c=maxY/2;
x=BOX_WIDTH;y=y_c; dx=STEP;
hdc = GetDC(hwnd);
memdc = CreateCompatibleDC(hdc);
hbit = CreateCompatibleBitmap (hdc,maxX,maxY); SelectObject (memdc, hbit);
hbrush = (HBRUSH)GetStockObject (BKGROUND_COLOR);
SelectObject (memdc, hbrush);
PatBlt (memdc, 0,0, maxX,maxY,PATCOPY);
hMyPen=CreatePen(PS_SOLID,5, RGB(255,255,0;
SelectObject(memdc,hMyPen);
ReleaseDC(hwnd, hdc);
break;
case WM_TIMER:
if (f)
{
if (x>maxX) x=0;
else x+=dx;
Rectangle(memdc,x-BOX_LENGTH,y-BOX_WIDTH,x+BOX_LENGTH,y+BOX_WIDTH);
InvalidateRect(hwnd,NULL,1);
}
break;
case WM_PAINT:
hdc=BeginPaint(hwnd,&paintstruct);
BitBlt(hdc,0,0,maxX,maxY, memdc,0,0,SRCCOPY);
EndPaint(hwnd,&paintstruct);
break;
case WM_COMMAND:
switch (LOWORD(wParam
{
case IDM_DRAW:
f=1
break;
case IDM_EXIT: DestroyWindow(hwnd);
break;
}
break;
case WM_DESTROY:
DeleteDC (memdc);
DeleteObject(hMyPen);
PostQuitMessage(0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
вот вся функция окна
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
static bool bDrawing = false;
static int nTimer;
static int nX = 0;
#define MAX_X 640
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_START:
if (bDrawing)
{
bDrawing = false;
KillTimer(hWnd, nTimer);
}
else
{
bDrawing = true;
nTimer = SetTimer(hWnd, 1, 50, NULL);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
Rectangle(hdc, nX-80, 240, nX, 240+40);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_TIMER:
if (bDrawing)
{
InvalidateRect(hWnd, NULL, 1);
nX++;
if (nX > MAX_X)
nX = 0;
}
break;
}
return 0;
}
int x, y, dx,dy;
заменить на
static int x, y, dx,dy;
хотя не могу понять почему мой вариант не работал..
Плюс, BitBlt почему-то выдаёт ошибку.
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
static HDC memdc = NULL;
static int x = 0, y = 0, dx = 0;
PAINTSTRUCT paintstruct;
#define STEP 5
#define BOX_HEIGHT 40
#define BOX_LENGTH 80
static bool bDrawing = false;
static int maxX = 0;
static int maxY = 0;
static int x_c, y_c;
static int nTimer;
static HBRUSH hbrush = NULL;
static HPEN hMyPen = NULL;
static HBITMAP hbit = NULL;
switch (message)
{
case WM_CREATE:
maxX = GetSystemMetrics (SM_CXSCREEN);
maxY = GetSystemMetrics (SM_CYSCREEN);
x_c = maxX/2;
y_c = maxY/2;
x = BOX_LENGTH;
y = y_c;
dx = STEP;
hdc = GetDC(hwnd);
memdc = CreateCompatibleDC(hdc);
hbit = CreateCompatibleBitmap (hdc, maxX, maxY);
SelectObject (memdc, hbit);
hbrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
SelectObject(memdc, hbrush);
PatBlt (memdc, 0, 0, maxX, maxY, PATCOPY);
hMyPen = CreatePen(PS_SOLID, 5, RGB(255,255,0;
SelectObject(memdc, hMyPen);
ReleaseDC(hwnd, hdc);
break;
case WM_TIMER:
if (bDrawing)
{
if (x > maxX + BOX_LENGTH)
x = 0;
else
x += dx;
PatBlt (memdc, 0, 0, maxX, maxY, PATCOPY);
Rectangle(memdc, x, y, x-BOX_LENGTH, y-BOX_HEIGHT);
InvalidateRect(hwnd,NULL,1);
}
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &paintstruct);
BitBlt(hdc, 0, 0, maxX, maxY, memdc, 0, 0, SRCCOPY);
EndPaint(hwnd, &paintstruct);
break;
case WM_COMMAND:
switch (LOWORD(wParam
{
case IDM_START:
if (bDrawing)
{
bDrawing = false;
KillTimer(hwnd, nTimer);
}
else
{
bDrawing = true;
nTimer = SetTimer(hwnd, 1, 50, NULL);
}
break;
case IDM_EXIT:
DestroyWindow(hwnd);
break;
}
break;
case WM_DESTROY:
DeleteDC (memdc);
DeleteObject(hMyPen);
DeleteObject(hbit);
PostQuitMessage(0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
Плюс, BitBlt почему-то выдаёт ошибку.
Еще бы не выдавать, HDC memdc тоже ведь поначалу не static был...
Не сцать, щас сделаю на WINAPI, -- у меня свой MFC есть
Эх опаздал Тяжко на моем MFC писать
На таймер плохо, особенно в 9х виндах (там вроде таймер чаще 18 раз в сек не сигналит). Лучше рисовать в отдельном потоке.
А WM_TIMER постится или сендтится?
А зачем битблитать в WM_PAINT и для этого инвалидейтить в WM_TIMER. Почему бы не заменить инвалидайт в WM_TIMER на битблит из WM_PAINT, а WM_PAINT удалить. Все равно не используешь paintstruct, Просто GetMessage пропускает WM_PAINT, если в очереди есть другие сообщения, поэтому при большом загрузе системы WM_TIMER будет выполняться, а WM_PAINT нет. Тогда вообще лучше перенести все из WM_TIMER в WM_PAINT, только оставить инвалидайт в WM_TIMER.
... WinMain (...)
{
while (running)
{
if (PeekMessage(...
{
}
//!сюда
}
}
а за временем следить через QueryPerformanceCounter / QueryPerformanceFrequency
ага
Оставить комментарий
soundag
вопрос элементарный, но мне как человеку никогда не работавшего с винапи сложныйкак выглядит обработка сообщений для написаний движения объекта в окне?
конкретно: прямоугольник движется по экрану.