Winapi

  • Автор темы solova
  • Дата начала
S

solova

#1
Создал совершенно чистый проект.
Нашёл работающий примерчик.
Создаю окошко:
Закрашиваю его: <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Код</div></div><div class="sp-body"><div class="sp-content">
C++:
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
HWND hWnd; 
MSG lpMsg;
WNDCLASS wc;
wc.style		 = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc  = WndProc;
wc.cbClsExtra	= 0;
wc.cbWndExtra	= 0;
wc.hInstance	 = hInstance;
wc.hIcon		 = NULL;	//LoadIcon(NULL, IDI_ICON);  
wc.hCursor	  = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW+2;//(HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "ClassName";
if (!RegisterClass(&wc))
{
MessageBox(NULL, "Не могу зарегистрировать класс окна!", "Ошибка", MB_OK);
return 0;
}
hWnd = CreateWindow("ClassName",		// Имя класса				  
"Шаблон WinAPI приложения",		 // Текст заголовка
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,		 // Стиль окна												 
50,50,				  // Позиция левого верхнего угла 
300,200,				// Ширина и высота окна	
NULL,					// Указатель на родительское окно NULL	
NULL,					// Используется меню класса окна			 
hInstance,			 // Указатель на текущее приложение
NULL);				 // Передается в качестве lParam в событие WM_CREATE
if (!hWnd){
MessageBox(NULL, "Не удается создать главное окно!", "Ошибка", MB_OK);
return 0;}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Выполняем цикл обработки сообщений до закрытия приложения
while (GetMessage(&lpMsg, NULL, 0, 0)) 
{
TranslateMessage(&lpMsg);
DispatchMessage(&lpMsg);
}
return (lpMsg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
RECT Rect;
HDC hdc, hCmpDC;
HBITMAP hBmp;
switch (message)
{
case WM_PAINT:
GetClientRect(hWnd, &Rect);
hdc = BeginPaint(hWnd, &ps);
// Создание теневогоs контекста для двойной буфферизации
hCmpDC = CreateCompatibleDC(hdc);
hBmp = CreateCompatibleBitmap(hdc, Rect.right - Rect.left,Rect.bottom - Rect.top);
SelectObject(hCmpDC, hBmp);
// Закраска фоновым цветом
LOGBRUSH br;
br.lbStyle = BS_SOLID;
br.lbColor = 0x333333;
HBRUSH brush;
brush = CreateBrushIndirect(&br);
FillRect(hCmpDC, &Rect, brush);
DeleteObject(brush);
// Копируем изображение из теневого контекста на экран
SetStretchBltMode(hdc, COLORONCOLOR);
BitBlt(hdc, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top,hCmpDC, 0, 0, SRCCOPY);
// Удаляем ненужные системные объекты
DeleteDC(hCmpDC);
DeleteObject(hBmp);
hCmpDC = NULL;
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return 0;
}
Цвет приятный в окне, но вот его голубая рамка (XP Style) просто раздражает.
Внимание, вопрос!
Можно ли этот цвет поменять\зарисовать как-то?
PS:(если предыдущее не возможно то)я видел окна без sysmenu и рамки, в MFC такое можно сделать установив "Title Bar"-FALSE, как такое создать через CreateWindow ?
 

a0z

Well-known member
15.03.2011
108
0
#2
Нужно обрабатывать сообщения WM_NCPAINT и прочие WM_NC*, которые отвечают за отрисовку неклиентской области окна.
 
S

solova

#3
Ну то что рамка не клиентская область и про WM_NC... я знаю.(перед тем как создавать тему я в нэте роюсь, но ни чего толкового не нашёл)
А как узнать HDC этой области.
и ещё , для окна(Кл. область) используется FillRect(hCmpDC, &Rect, brush); а для рамки то надо?

И вообще я со всякими отрисовками и HBRUSH-ами в первые сталкиваюсь поэтому мне бы как то по подробнее.
Этот код не мой, поэтому хочу спросить, а создавать "теневой контекст для двойной буфферизации" надо обязательно или можно просто сразу зарисовать мой "hdc"? тогда просто HBITMAP hBmp; не нужен будет.
 
S

solova

#5
lazybiz
ну как бы то что нужно
только его двигать нельзя
WMPlayer 11 без рамки(хотя её можно включить) но там как то реализуется убирание этой рамки окно выглядит как попуп, но его двигать можно.
 

a0z

Well-known member
15.03.2011
108
0
#6
А как узнать HDC этой области.
GetWindowDC

и ещё , для окна(Кл. область) используется FillRect(hCmpDC, &Rect, brush); а для рамки то надо?
Да всё тоже самое.

Этот код не мой, поэтому хочу спросить, а создавать "теневой контекст для двойной буфферизации" надо обязательно или можно просто сразу зарисовать мой "hdc"? тогда просто HBITMAP hBmp; не нужен будет.
Не обязательно, но может напиятно моргать и дёргаться.

Хотя, если стиль тулбара устраивает, то можно не мучаться. А перемещения отрабатывать через WM_LBUTTONDOWN/WM_LBUTTONUP + GetCapture
 

lazybiz

Well-known member
03.11.2010
1 339
0
#7
solova
1. Смотри. Создаешь окно со стилем WS_POPUP.
2. В процедуре окна прописываешь следующее на обработчик сообщений:
C++:
case WM_NCHITTEST: return HTCAPTION;
 

lazybiz

Well-known member
03.11.2010
1 339
0
#9
И еще:
При срабатывании WM_NCHITTEST, lParam имеет: в нижнем слове - координату X курсора, в верхнем - Y --- относительно верхнего-левого угла экрана! НЕ ОКНА!
Т.е., можно координаты экрана преобразовать в пространство окна и задать область.. скажем в 32 пикселя от верхней границы окна:
C++:
	case WM_NCHITTEST: {
POINT	pt;
pt.x = LOWORD( lParam );
pt.y = HIWORD( lParam );
ScreenToClient( hWnd, &pt );
if ( pt.y < 32 ) return HTCAPTION;
} break;
 
S

solova

#10
ещё один вопросик
как сделать обработчик кнопки
собсно сама кнопка
C++:
CreateWindowEx(NULL,L"Button",L"Button1",WS_VISIBLE|WS_CHILD,10, 70, 90, 40,hWnd,IDB_Button1, hInstance, NULL );
в мфц там проще но тут пока не знаю как
думаю отлавливать WM_COMAND. Можно(а может нужно) как-то по другому?

а ну вот всё получилось<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">код</div></div><div class="sp-body"><div class="sp-content">
C++:
#define IDB_Button1 1
...
case WM_COMMAND:
if(wParam == IDB_Button1)
MessageBox(NULL,L"Нажата кнопка Button 1",L"Message WM_COMMAND",MB_OK);
 

lazybiz

Well-known member
03.11.2010
1 339
0
#11
Почти все как ты написал, только немного проще:
C++:
...
case WM_COMMAND:
...
switch ( LOWORD( wParam ) ) {
...
case IDB_Button1:
MessageBox( NULL, L"Нажата кнопка Button 1", L"Message WM_COMMAND", MB_OK );
break;

...
} break;
...
...
На всякий случай увеличь значение идентификатора IDB_Button1 например:
C++:
#define IDB_Button1 1001
И еще. Зачем создавать кнопку через CreateWindowEx, если расширенный стиль (первый параметр) у тебя выставлен в NULL ? Функция CreateWindowEx отличается от CreateWindow только только тем что у нее есть параметр расширенного стиля.
 
S

solova

#12
Зачем создавать кнопку через CreateWindowEx, если расширенный стиль (первый параметр) у тебя выставлен в NULL
у меня был там параметр но тут я его убрал для лучшей читабельности кода.
На всякий случай увеличь значение идентификатора IDB_Button1 например:
#define IDB_Button1 1001
а к чему может привести маленький ID? (может присваивать какой то "WM_USER+..." ?)

а switch в WM_COMMAND буду использовать позже, когда кнопок будет больше
спасибаа
 

lazybiz

Well-known member
03.11.2010
1 339
0
#13
а к чему может привести маленький ID?
В WM_COMMAND скорее всего ни к чему, хотя черт его знает...

может присваивать какой то "WM_USER+..."
Нннет. Смысл схож но не совсем то. WM_USER + X - это если ты добавляешь какое-то свое сообщение непосредственно окну, а тут ты добавляешь идентификатор кнопки. Все-таки немного разные вещи.

Пожалуйста.