Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.05.2013, 23:00   #1
Sorento2
Пользователь
 
Регистрация: 13.11.2012
Сообщений: 41
По умолчанию WinApi приложение. Задвигающаяся занавеска.

Что нужно: нарисовать окно, карниз. За окном ночь(черный цвет), стены серые, окна белые, карниз зеленый и занавеска голубая. Занавеска по нажатию клавиш влево и вправо должна выдвигаться на 3 пикселя. Толщина сложенной занавески 5 пикселей.
Что сделано:
Код:
#include <Windows.h>
#include <WindowsX.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
HDC hdc;
HBRUSH okn=CreateSolidBrush(RGB(255,255,255)); //белый
HBRUSH stena=CreateSolidBrush(RGB(105,105,105)); //серый
HBRUSH karniz=CreateSolidBrush(RGB(0,255,0)); //зеленый
HBRUSH zanaves=CreateSolidBrush(RGB(0,204,255)); //голубой
HBRUSH nocc=CreateSolidBrush(RGB(0,0,0));


HPEN line=CreatePen(PS_SOLID,2,RGB(0,0,0)); //черный


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASS wc     = {0};
	wc.style        = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc  = WndProc;
    wc.hInstance    = hInstance;
	wc.hCursor      = LoadCursor (NULL, IDC_ARROW);
    wc.lpszClassName= "CMyWnd";

    RegisterClass (&wc);
	HWND hWnd = CreateWindow ("CMyWnd", "Мяч Лестница", WS_THICKFRAME, 20, 20, 480, 500, NULL, NULL, hInstance, NULL);
	hdc = GetDC (hWnd);
	ShowWindow (hWnd, nCmdShow);
    //SetTimer (hWnd, 1, USER_TIMER_MINIMUM, NULL);  
	RECT sten; sten.left = 20; sten.top=20; sten.bottom=440; sten.right=440;
	RECT okno; okno.left = 80; okno.top=80; okno.bottom=380; okno.right=380;
	RECT noch; noch.left = 100; noch.top=100; noch.bottom=360; noch.right=360;
	RECT karn; karn.left = 75; karn.top=50; karn.bottom=60; karn.right=385;
	RECT ram1; ram1.left = 180; ram1.top = 99; ram1.bottom = 361; ram1.right = 190;
	RECT ram2; ram2.left = 270; ram2.top = 99; ram2.bottom = 361; ram2.right = 280;
	RECT zana; zana.left = 75; zana.top = 60; zana.bottom = 390; zana.right = 80;
	FillRect(hdc, &sten, stena);
	FillRect(hdc, &okno, okn);
	FillRect(hdc, &noch, nocc);
	FillRect(hdc, &karn, karniz);
	FillRect(hdc, &ram1, okn);
	FillRect(hdc, &ram2, okn);
	FillRect(hdc, &zana, zanaves);
	
	MSG msg;
while (GetMessage(&msg,NULL,0,0)>0)
{TranslateMessage (&msg);
 DispatchMessage (&msg);
}
return msg.wParam;


}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent, key;
	PAINTSTRUCT ps;
	HDC hdc;
	RECT zanav;
	zanav.bottom = 390;
	zanav.left = 78;
	zanav.top = 60;
	zanav.right = 83;
	switch (message)
	{

		HDC hdc;
	case WM_KEYDOWN:

		if(wParam==VK_ESCAPE)
		{
		PostQuitMessage(0); 
	    return 0;
		} 

		if(wParam==VK_RIGHT)
		{
			FillRect(hdc, &zanav, zanaves);
		}
		break;
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
Что непонятно: Так как это мое первое приложение на WinApi, несколько вопросов:
1. Непонятно, как рисовать через wm_paint? Ну то есть, как отправить сообщение в wm_paint из wm_keydown, что бы что то нарисовать. С помощью чего они вообще обмениваются сообщениями. (хотя бы примеры или литературу)
2. Ну ладно. Я примерно понимаю, как сдвигать занавеску вправо. Но как её сдвигать влево? Что произойдет с картинкой под занавеской?
3. Почему у меня сейчас не реагирует на VK_RIGHT?
Сейчас в VK_RIGHT просто попробовал что нибудь нарисовать.
Вот в общем, кому не лень прошу помочь

Последний раз редактировалось Sorento2; 02.05.2013 в 23:23.
Sorento2 вне форума Ответить с цитированием
Старый 03.05.2013, 10:37   #2
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Цитата:
Сообщение от Sorento2 Посмотреть сообщение
Что непонятно: Так как это мое первое приложение на WinApi, несколько вопросов:
1. Непонятно, как рисовать через wm_paint?
Все процедуры рисования помещаете в WudProc в ветку обработки WM_PAINT.
Цитата:
Ну то есть, как отправить сообщение в wm_paint из wm_keydown, что бы что то нарисовать. С помощью чего они вообще обмениваются сообщениями. (хотя бы примеры или литературу)
Сообщения посылать не надо. Пользуетесь InvalidateRect для того фрагмента изображения (или для изображения целиком), которое нужно обновить.
Цитата:
2. Ну ладно. Я примерно понимаю, как сдвигать занавеску вправо. Но как её сдвигать влево?
Точно так же.
Цитата:
Что произойдет с картинкой под занавеской?
При обновлении региона перерисовывается все его содержимое. Т.е. в WM_PAINT Вы сначала рисуете то, что за занавеской, а потом саму занавеску. При каждой перерисовке все эти операции будут повторяться с начала (но только для указанного региона).
Здесь, правда, может возникнуть такой неприятный эффект как мерцание изображения, т.к. весь цикл рисования повторяется с начала. Если требуется этого избежать - применяют буферизацию.
Цитата:
3. Почему у меня сейчас не реагирует на VK_RIGHT?
Сейчас в VK_RIGHT просто попробовал что нибудь нарисовать.
Вот в общем, кому не лень прошу помочь
А почему Вы решили, что "не реагирует"? Может, реагирует, но Вы этого просто не видите?
s-andriano вне форума Ответить с цитированием
Старый 03.05.2013, 17:55   #3
Sorento2
Пользователь
 
Регистрация: 13.11.2012
Сообщений: 41
По умолчанию

Два вопроса:
Можете привести пример нажатия клавиши и отрисовки соответсвующей этой клавише? Я просто не очень понял этот момент. Обработка нажатия клавиши идет в WM_KEYDOWN, отрисовка в WM_PAINT. Как они ну "общаются" что ли.
И второй: я так понял вы говорите о двойной буферизации?
Sorento2 вне форума Ответить с цитированием
Старый 03.05.2013, 17:57   #4
Sorento2
Пользователь
 
Регистрация: 13.11.2012
Сообщений: 41
По умолчанию

Два вопроса:
Можете привести пример нажатия клавиши и отрисовки соответсвующей этой клавише? Я просто не очень понял этот момент. Обработка нажатия клавиши идет в WM_KEYDOWN, отрисовка в WM_PAINT. Как они ну "общаются" что ли.
И второй: я так понял вы говорите о двойной буферизации? Блин второе случайно получилось
Sorento2 вне форума Ответить с цитированием
Старый 03.05.2013, 18:33   #5
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Цитата:
Сообщение от Sorento2 Посмотреть сообщение
Два вопроса:
Можете привести пример нажатия клавиши и отрисовки соответсвующей этой клавише? Я просто не очень понял этот момент. Обработка нажатия клавиши идет в WM_KEYDOWN, отрисовка в WM_PAINT. Как они ну "общаются" что ли.
И второй: я так понял вы говорите о двойной буферизации?
Я не понимаю, что такое "отрисовка соответствующая этой клавише".
В моем понимании цикл взаимодействия интерактивной программы с человеком включает:
- контроль за состоянием органов управления, например, клавиатуры и мыши,
- изменения текущего состояния программы, вызванные:
а) управляющим воздействием (те самые мышь и клавиатура),
б) внутренними процессами программы (например, что-то должно двигаться безотносительно действий пользователя),
- отрисовка нового состояния программы.

При изменении внутреннего состояния (достаточного для того, чтобы инициировать перерисовку) дается команда InvalidateRect, которая говорит, что данный фрагмент изображения нуждается в перерисовке. Перерисовка, естественно, должга производиться уже по новому состоянию.

Мне не нравится термин "двойная буферизация", т.к. это дословный перевод, не учитывающий различий смысла английского слова "buffer" и русского "буфер". По-русски правильно это было бы назвать просто буферизацией, - т.е. Вы рисуете не сразу на экране, а в некотором буфере, а когда изображение готово, целиком перекидываете его на экран.
s-andriano вне форума Ответить с цитированием
Старый 03.05.2013, 18:43   #6
Sorento2
Пользователь
 
Регистрация: 13.11.2012
Сообщений: 41
По умолчанию

Прошу прощения, все понял)
Sorento2 вне форума Ответить с цитированием
Старый 03.05.2013, 19:18   #7
Sorento2
Пользователь
 
Регистрация: 13.11.2012
Сообщений: 41
По умолчанию

Код:
case WM_PAINT:
	hdc=BeginPaint(hWnd, &ps);
	
	RECT sten; sten.left = 20;	sten.top=20;	sten.bottom=440;	sten.right=440;
	RECT okno; okno.left = 80;	okno.top=80;	okno.bottom=380;	okno.right=380;
	RECT noch; noch.left = 100; noch.top=100;	noch.bottom=360;	noch.right=360;
	RECT karn; karn.left = 75;	karn.top=50;	karn.bottom=60;		karn.right=385;
	RECT ram1; ram1.left = 180; ram1.top = 99;	ram1.bottom = 361;	ram1.right = 190;
	RECT ram2; ram2.left = 270; ram2.top = 99;	ram2.bottom = 361;	ram2.right = 280;
	RECT zana; zana.left = 75;	zana.top = 60;	zana.bottom = 390;	zana.right = 80;
	zanav.l=zana.left; zanav.t=zana.top; zanav.b=zana.bottom; zanav.r=zana.right;
	FillRect(hdc, &sten, stena);
	FillRect(hdc, &okno, okn);
	FillRect(hdc, &noch, nocc);
	FillRect(hdc, &karn, karniz);
	FillRect(hdc, &ram1, okn);
	FillRect(hdc, &ram2, okn);
	FillRect(hdc, &zana, zanaves);
	//InvalidateRect(hWnd, &zana, FALSE);
	if(DvizhR=true){
	SelectObject(hdc, zanaves);
	Rectangle(hdc, zanav.l, zanav.t, zanav.r,zanav.b);
	zanav.r=+3;}
	EndPaint(hWnd, &ps);
	case WM_KEYDOWN:
	switch(wParam){
	case VK_ESCAPE:
		PostQuitMessage(0); 
		break;
	case VK_RIGHT:
		DvizhR=true;
		break;
	}
Вот так возможно осуществить?
Sorento2 вне форума Ответить с цитированием
Старый 03.05.2013, 20:28   #8
Sorento2
Пользователь
 
Регистрация: 13.11.2012
Сообщений: 41
По умолчанию

Вот) Наконец то получилось) мерцания не появилось. Вопроса теперь 2:
1. Почему не сразу реагирует на клавишу после нажатия другой, а то и делает функции другой?(на протяжении где-то 2 нажатий)
2. Почему вправо и влево работают с нажатием Ctrl u Shift?


Код:
#include <Windows.h>
#include <WindowsX.h>
#include <cmath>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
HDC hdc;
HBRUSH okn=CreateSolidBrush(RGB(255,255,255)); //белый
HBRUSH stena=CreateSolidBrush(RGB(105,105,105)); //серый
HBRUSH karniz=CreateSolidBrush(RGB(0,255,0)); //зеленый
HBRUSH zanaves=CreateSolidBrush(RGB(0,204,255)); //голубой
HBRUSH nocc=CreateSolidBrush(RGB(0,0,0));

HPEN line=CreatePen(PS_SOLID,2,RGB(0,0,0)); //черны
struct ZANA{int t, l, r, b, r1, l1;} zanav;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	zanav.r1=83;
	WNDCLASS wc     = {0};
	wc.style        = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc  = WndProc;
    wc.hInstance    = hInstance;
	wc.hCursor      = LoadCursor (NULL, IDC_ARROW);
	wc.hbrBackground = NULL;
    wc.lpszClassName= "wnd";

    RegisterClass (&wc);
	HWND hWnd = CreateWindow ("wnd", "Занавеска", WS_THICKFRAME, 20, 20, 480, 500, NULL, NULL, hInstance, NULL);
	hdc = GetDC (hWnd);
	ShowWindow (hWnd, nCmdShow);

	MSG msg;
			while (GetMessage(&msg,NULL,0,0)>0)
			{TranslateMessage (&msg);
			DispatchMessage (&msg);
			}
			return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	bool Dvizh_R=false, Dvizh_L=false;
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;
	switch (message)
	{

	HDC hdc;
	case WM_KEYDOWN:
		switch(wParam){
			case VK_ESCAPE:
				PostQuitMessage(0); 
				break;
			case VK_RIGHT:
				Dvizh_R=true;
				InvalidateRect(hWnd,0,FALSE);
				break;
			case VK_LEFT:
				Dvizh_L=true;
				InvalidateRect(hWnd,0,FALSE);
					}
	case WM_PAINT:
	hdc=BeginPaint(hWnd, &ps);
	
	RECT sten; sten.left = 20;	sten.top=20;	sten.bottom=440;	sten.right=440;
	RECT okno; okno.left = 80;	okno.top=80;	okno.bottom=380;	okno.right=380;
	RECT noch; noch.left = 100; noch.top=100;	noch.bottom=360;	noch.right=360;
	RECT karn; karn.left = 75;	karn.top=50;	karn.bottom=60;		karn.right=385;
	RECT ram1; ram1.left = 180; ram1.top = 99;	ram1.bottom = 361;	ram1.right = 190;
	RECT ram2; ram2.left = 270; ram2.top = 99;	ram2.bottom = 361;	ram2.right = 280;
	RECT zana; zana.left = 75;	zana.top = 60;	zana.bottom = 390;	zana.right = 80;
	
	zanav.l=75; zanav.t=60; zanav.b=390; zanav.r=80;

	FillRect(hdc, &sten, stena);
	FillRect(hdc, &okno, okn);
	FillRect(hdc, &noch, nocc);
	FillRect(hdc, &karn, karniz);
	FillRect(hdc, &ram1, okn);
	FillRect(hdc, &ram2, okn);
	SelectObject(hdc, zanaves);
	Rectangle(hdc, 75, zanav.t, zanav.r1,zanav.b);
	if(Dvizh_R == true && zanav.r1<385){
	SelectObject(hdc, zanaves);
	Rectangle(hdc, 75, zanav.t, zanav.r1,zanav.b);
	zanav.r1+=3;
	Dvizh_R = true;
	}
	if(Dvizh_L == true && zanav.r1>80)
	{
		SelectObject(hdc, zanaves);
	Rectangle(hdc, 75, zanav.t, zanav.r1,zanav.b);
	zanav.r1-=3;
	}
	EndPaint(hWnd, &ps);
	
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
Sorento2 вне форума Ответить с цитированием
Старый 03.05.2013, 22:58   #9
Sorento2
Пользователь
 
Регистрация: 13.11.2012
Сообщений: 41
По умолчанию

То есть если я нажимаю на левую после нажатия правой клавиши, то она один раз работает как правая. то есть двигает занавеску вправо.
Sorento2 вне форума Ответить с цитированием
Старый 03.05.2013, 23:44   #10
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Честно говоря, не понял Ваших манипуляций с клавиатурой и отрисовкой.
Клавиатура меняет состояние, а отрисовка его не меняет. Не знаю, чего Вы добивались, но присваивать переменным состояния какие-то значения в процессе отрисовки не следует.
s-andriano вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Различие кода mfc и WinApi(mfc ручками набили, а WinApi автоматически с генерировался!! нужно явное отличие, не могу найти) Артём1991 Помощь студентам 0 25.03.2012 17:13
Первое приложение на WinAPI m9yt Общие вопросы C/C++ 1 03.09.2010 22:02
Задача:в вижуал с++ Разработать приложение-сервер и приложение (смотри дальше сообщение) Мила777 Фриланс 2 21.10.2009 11:05
WinApi Necrom Помощь студентам 3 27.06.2008 14:24
WinApi Andr Безопасность, Шифрование 3 17.06.2007 13:38