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

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

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 15.03.2010, 18:01   #1
Dimarik
Форумчанин
 
Аватар для Dimarik
 
Регистрация: 18.04.2009
Сообщений: 688
По умолчанию HELLO WORD!

Добрый вечеР! написал программу, разбирая из книжки и кучи интернетовских страниц. Итог: компилятор выдал 4 ошибки и куча кода непонятна. Ответьте плиз на вопросы, которые в комментариях.
ОШИБКИ:
Warning 1 warning C4003: not enough actual parameters for macro 'CreateWindowA' c:\documents and settings\dimarik \мои документы\visual studio 2008\projects\hello_word\hello_word \hello.cpp 41 hello_word
Error 2 error C2059: syntax error : ',' c:\documents and settings\dimarik \мои документы\visual studio 2008\projects\hello_word\hello_word \hello.cpp 41 hello_word
Error 3 error C2039: 'wParem' : is not a member of 'tagMSG' c:\documents and settings\dimarik \мои документы\visual studio 2008\projects\hello_word\hello_word \hello.cpp 69 hello_word
Error 4 error C2660: 'DrawTextA' : function does not take 4 arguments c:\documents and settings\dimarik \мои документы\visual studio 2008\projects\hello_word\hello_word \hello.cpp 86 hello_word

а вот и сам код
Код:
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT,WPARAM, LPARAM);//что это такое????
//Как я понял в этой функции будет производиться обработка сообщений окна? если так, то зачем
/* цикл
while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);//это типа переводит сообщение
		DispatchMessage(&msg);//это типа отправляет сообщение, так?
		//если это так, то прокомменте плиз по-простому работу функций
	}
	*/
char szWinName[] = "MyWin"; /* Имя класса окна */

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,
        LPSTR lpszArgs, int nCmdShow)
{
	/*сначало нужно подготовить и зарегестрировать
	класс окна с требуемыми характкристиками*/
	HWND hMainWnd;
	MSG msg;
	WNDCLASSEX wc;
	wc.cbSize = sizeof(wc);
	wc.lpfnWndProc = WndProc;//в этой строке мы указываем, что будем производить обработку сообщений для нашего окна 
	//ТАК????? но WndProc - это ж по идее функция, где её параметры????
	wc.hInstance = hInstance;//что делает?
	wc.lpszClassName = "My Class";
	/* поскольку у этой структуры значительно больше полей, остальные мы сделаем нулём*/
	memset(&wc,0,wc.cbSize);
	
	//Далее нужно зарегестрировать класс окна
	RegisterClassEx(&wc);
	/*В одной книге написано исспользовать RegisterClassEx(&wc), а в другой 
	RegisterClass(&wc). Почему-то когда пользуюсь RegisterClass(&wc)
	выскакивает ошибка, связанная с преобразованием типов. почему?*/

	//Далее создаём окно
	hMainWnd = CreateWindow(szWinName, "APPLICATION", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0,
		(HWND)NULL, (HMENU)NULL, 
		(HINSTANCE)hInstance,
		NULL);
/*z я посмотрел в MSDN по этой функции и вот что нашёл:
HWND CreateWindow(LPCTSTR lpClassName,
    LPCTSTR lpWindowName,
    DWORD dwStyle,
    int x,
    int y,
    int nWidth,
    int nHeight,
    HWND hWndParent,
    HMENU hMenu,
    HINSTANCE hInstance,
    LPVOID lpParam
);
вопрос состоит в этих параметрах: HINSTANCE hInstance, HWND hWndParent
и ещё. LPVOID lpParam отвечает за многооконное приложение, так?*/
	ShowWindow(hMainWnd, nCmdShow);//показываем окно
	UpdateWindow(hMainWnd);//обновляем окно. ЗАЧЕМ??????

	/*выполняем цикл обработки сообщений до закрытия приложения.
	ЗАЧЕМ???? Потому что свернуть, развернуть окно, закрыть окно это тоже сообщение?
	*/
	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);//это типа переводит сообщение
		DispatchMessage(&msg);//это типа отправляет сообщение, так?
		//если это так, то прокомменте плиз по-простому работу функций
	}
return msg.wParem;//что это за поле у структуры msg?
}

//Далее идёт описание функции WndProc, в котором НИЧЕГО не понятно. поясните, плиз
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	HDC hDC;//что это за переменная?
	PAINTSTRUCT ps;//что это за переменная?
	RECT rect;//что это за переменная?

	switch(uMsg)//поясните плиз этот блок switch с case`ами
	{
	case WM_PAINT:
		hDC = BeginPaint(hWnd, &ps);

		GetClientRect(hWnd, &rect);
		DrawText(hDC, "HELLOW, WORD!!!!!!!!" -1, &rect,
			DT_SINGLELINE|DT_CENTER|DT_VCENTER);
		EndPaint(hWnd,&ps);
		break;

	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;
		
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	return 0;
}
P.S. не судите строго, я ток начинаю винапи юзать)
Dimarik вне форума Ответить с цитированием
Старый 15.03.2010, 18:56   #2
Ivan_32
somewhere else
Участник клуба
 
Аватар для Ivan_32
 
Регистрация: 17.07.2008
Сообщений: 1,409
По умолчанию

Код:
//Эта директива на случай если по умолчанию в приложении используется Unicode версии функции - мы работает с ANSI
//Если убрать эту директиву - скорее всего при вызове макросов, скажем CreateWindow(да да это макрос на самом деле) 
//Будет вызван CreateWindowW (все UNICODE функции имеют окончание W), а если не убирать - CreateWindowA
//О самом Юникоде и прочих особенностях можно почитать попозже - сейчас это не так важно. 
#undef UNICODE

#include <windows.h>

LRESULT WINAPI WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgs,int nCmdShow)
{
	MSG msg;
	/*
	Разберем что же это за структура такая: 
	HWND hwnd; - хендл окна к которому пришло сообщение - дескриптор или индетификатор если угодно.
	UINT message; - номер сообщения которое пришло. 
	WPARAM wParam; - первый параметр 
	LPARAM lParam; - второй параметр
	DWORD time; - штамп времени
	POINT pt; - кординаты курсора в момент события.
	*/
	HWND hWnd;
	WNDCLASS wc;
	wc.cbClsExtra=0; //Неиспользуемый параметр но надо заполнить нулем
	wc.cbWndExtra=0; //Неиспользуемый параметр но надо заполнить нулем
	wc.hbrBackground=(HBRUSH)COLOR_WINDOW+1; //Этот параметр задает цвет фона. Есть набор цветов для фона окна.
	wc.hCursor=LoadCursor(0,IDC_ARROW); //Загружаем в прогрумму курсор из системы.
	wc.hIcon=LoadIcon(0,IDI_APPLICATION); //Тоже самое и иконкой. Она отображается в левом верхнем углу рамки окна.
	wc.hInstance=hInstance; //Тут думаю понятно - мало ли какой внутренней функции понадобится дескриптор нашего приложения.
	wc.lpfnWndProc=WndProc; //Далее параметру lpfnWndProc присваивается АДРЕСС функции обработки сообщений.
	wc.lpszClassName="HelloWorldWindowClass"; //Заполняем поле названия нашего класса.
	wc.lpszMenuName=0; //Заполняем нулем, т.к. меню у нас нет. 
	wc.style=CS_HREDRAW|CS_VREDRAW; //Эти параметры сигнализируют системе что наше окно будет перерисовано при вертикальных и горизонтальных изменениях.

	RegisterClass(&wc);
	//Отныне в системе есть наш зарегистрированный класс окна.

	CreateWindow("HelloWorldWindowClass", //Мы обращаемся к системе, она нам создаст окно класса имя которого указывается в этом параметре.
				"Hello, World!", //Имя нашего окна - отображается на рамке окна. 
				WS_VISIBLE|WS_SYSMENU, //Это стили окна. WS_VISIBLE - окно создается уже видимым. И WS_SYSMENU создает в правом вехнем углу кнопочку закрыть(крестик т.е.)  
				0,0 //Начальные кординаты окна создадим в левом верхнем углу экрана - там начинается отсчет кординат.
				,320,240, //Размер окна. 320 в ширину и 240 в высоту
				0,0, // два неиспользуемых параметра
				hInstance, // дадим и окну дескриптор нашего приложения
				0); //Последний параметр тоже не используется


	//А вот теперь начинается самое интересное:
	//Когда вы что ни будь делаете мышкой клавиатурой итд, т.е. взаимодействуете с компьютером
	//Система региструрет как сообщение и всем окнам на которые оно могло повлиять - рассылается сообщение.
	//Функция GetMessage постоянно спрашивает систему - не было ли для нее сообщений. 
	//Как только сообщения закончатся - функция вернет 0 и цикл прекратится. 
	//Но система постоянно отдает этой функции сообщения болванки - что б она не возвращала 0.
	//Если в систему послать сообщение о том что окну пора закрытся - система перестанет отдавать сообщения болванки. 
	//Get Message получает сообщение и параметры для него и записывает в структуру msg - мы ее адрес передаем первым параметром.
	while(GetMessage(&msg,0,0,0)!=NULL)
	{
		//А вот это уже ближе к делу: эта функция вызывает нашу процедуру обработки сообщений с параметрами из структуры MSG
		DispatchMessage(&msg);
	}
	return 0;
};
LRESULT WINAPI WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	//Все очень просто. То что нам надо мы обрабатываем.
	switch(uMsg)
	{
	//А нужно нам обрабатывать только сообщение WM_CLOSE
	//Система его присылает окну, когда окно пытаются закрыть. 
	//Скажем когда пользователь жмет на "Крестик". 
	case WM_CLOSE:
		{
			//Эта функция сообщает системе что нам пора закрыватся. 
			//Единственный параметр - это код ошибки. 
			// 0 означает  "Нет Ошибки".
			PostQuitMessage(0);
		}return 0; //После обработки сообщения - возвращаем результат.
	default:
		//То что не надо - передаем системе и она делает работу за нас.
		return DefWindowProc(hWnd,uMsg,wParam,lParam);
	}
}
И на всякий случай еще здесь можно посмотреть:
http://paste.org/pastebin/view/16352
"Тяжело в учении, легко в бою" - А.В. Суворов

Последний раз редактировалось Stilet; 05.02.2011 в 15:55.
Ivan_32 вне форума Ответить с цитированием
Старый 15.03.2010, 19:42   #3
Dimarik
Форумчанин
 
Аватар для Dimarik
 
Регистрация: 18.04.2009
Сообщений: 688
По умолчанию

СПАСИБО!!!!! ОГРОМНОЕ!
Dimarik вне форума Ответить с цитированием
Старый 15.03.2010, 19:59   #4
Ivan_32
somewhere else
Участник клуба
 
Аватар для Ivan_32
 
Регистрация: 17.07.2008
Сообщений: 1,409
По умолчанию

Кстати по поводу RegisterClass и RegisterClassEx - синтаксическая ошибка возникала из за того что эти две функции используют разные версии структуры класс-окна.
WNDCLASS и WNCLASSEX соответственно. У второй кроме всего прочего есть параметр cbSize (который кстати нужно обязательно задать) - размер класса окна. Это для контроля версии структуры. На случай если появится Windows 0xFFFFFFFF в которой эта структура изменится
"Тяжело в учении, легко в бою" - А.В. Суворов
Ivan_32 вне форума Ответить с цитированием
Старый 16.03.2010, 20:03   #5
Dimarik
Форумчанин
 
Аватар для Dimarik
 
Регистрация: 18.04.2009
Сообщений: 688
По умолчанию

На случай если появится Windows 0xFFFFFFFF в которой эта структура изменится.
Если можно, с этого момента поподробней))) ничё не понял)))
Dimarik вне форума Ответить с цитированием
Старый 16.03.2010, 20:08   #6
Ivan_32
somewhere else
Участник клуба
 
Аватар для Ivan_32
 
Регистрация: 17.07.2008
Сообщений: 1,409
По умолчанию

Ну например если в Windows 8 появится новая версия этой структуры, которая будет на 2 байта длинней. Система проверит какую вы используете - старую или новую версию и использует нужную функцию(внутреннюю - это все происходит за кадром скажем так). В любом случае это всего лишь детали, о которых пока задумываются, думаю, рано.
"Тяжело в учении, легко в бою" - А.В. Суворов
Ivan_32 вне форума Ответить с цитированием
Старый 17.03.2010, 16:53   #7
Dimarik
Форумчанин
 
Аватар для Dimarik
 
Регистрация: 18.04.2009
Сообщений: 688
По умолчанию

wc.style=CS_HREDRAW|CS_VREDRAW; //Эти параметры сигнализируют системе что наше окно будет перерисовано при вертикальных и горизонтальных изменениях.
пардон, с побитовым ИЛИ никогда не работал. почему нужно именно побитовое ИЛИ использовать, а не просто ИЛИ????
ну и естественно, аналогичный вопрос с
WS_VISIBLE|WS_SYSMENU, //Это стили окна. WS_VISIBLE - окно создается уже видимым. И WS_SYSMENU создает в правом вехнем углу кнопочку закрыть(крестик т.е.)

как я понимаю, побитовое или - это дизъюнкиция, побитовое и - коньюнкция. то есть 1|0 == 1; 1&0 == 0. Только вот при чём тут это я не понимаю. Если возможно, разъясните попонятней, плиз

Последний раз редактировалось Stilet; 05.02.2011 в 15:56.
Dimarik вне форума Ответить с цитированием
Старый 17.03.2010, 17:25   #8
Ivan_32
somewhere else
Участник клуба
 
Аватар для Ivan_32
 
Регистрация: 17.07.2008
Сообщений: 1,409
По умолчанию

Ну для задания стиля используется DWORD, каждый бит которого что то значит. А эти значения - WS_VISIBLE - это веса битов. Для примера возьмем байт:
0000 0000
Допустим самый верхний бит(самый левый т.е.) сигнализирует о том что система будет отображать окно круглой формы, а бит номер 3(нумерация с нуля) означает что окно будет отображаться сразу после создания.
Следовательно нам нужно установить сразу два бита. Вес бита это его 2 в степени его порядкового номера. Т.е. получается что нам нужно взять
00001000 и 10000000 и сделать с ними OR, полученное значение и будет нужной нам конфигурацией флагов.
10000000 = 128
OR
00001000 = 8
=
10001000 = 136
для того что б сбросить определенный бит, нужно сделать AND. Например нужно сбросить 3-й бит. Для этого придется сделать инверсию поля с единственным, сбрасываемым нами, битом(т.е. сделать инверсию 00001000) и сделать AND этой инверсии с нашим битовым полем.
В С++ инверсия обозначается ~ тильдой.
BYTE test= 0;
test |= 00001000 | 10001000; //устанавливаем биты 7 и 3.
test &= ~00001000; // и сбрасываем 3-й - нумерация то с нуля.

Т.е. я собственно к чему веду.
Предположим что тот же WS_VISIBLE = 00001000b а WS_SYSMENU = 10000000b. Что б сразу записать и то и другое нужно это значение скомбинировать OR-ом и тогда получится искомая конфигурация этого битового поля.
"Тяжело в учении, легко в бою" - А.В. Суворов

Последний раз редактировалось Ivan_32; 17.03.2010 в 17:34.
Ivan_32 вне форума Ответить с цитированием
Старый 17.03.2010, 17:49   #9
Dimarik
Форумчанин
 
Аватар для Dimarik
 
Регистрация: 18.04.2009
Сообщений: 688
По умолчанию

понял. только есть один вопрос. что представляет собой тип DWORD? это как я понял не целочисленный тип.
и ещё. попробовал малость преобразовать switch. итог: 2 ошибки.
Цитата:
Error 1 error C2059: syntax error : '-' c:\documents and settings\dimarik \мои документы\visual studio 2008\projects\hello_word\hello_word \hello.cpp 81 hello_word
Error 2 error C2228: left of '.EndPaint' must have class/struct/union c:\documents and settings\dimarik \мои документы\visual studio 2008\projects\hello_word\hello_word \hello.cpp 83 hello_word
Код:
switch(uMsg)
    {
    //А нужно нам обрабатывать только сообщение WM_CLOSE
    //Система его присылает окну, когда окно пытаются закрыть. 
    //Скажем когда пользователь жмет на "Крестик". 
		case WM_CLOSE:
            //Эта функция сообщает системе что нам пора закрыватся. 
            //Единственный параметр - это код ошибки. 
            // 0 означает  "Нет Ошибки".
            PostQuitMessage(0);
			break; //После обработки сообщения - возвращаем результат.
		case WM_PAINT:
			hDC = BeginPaint(hWnd, &ps);
			GetClientRect(hWnd, &rect);
			DrawText(hDC, "Hello world!". -1, &rect,
				DT_SINGLE|DT_CENTER|DT_VCENTER);
			EndPaint(hWnd, &ps);
			break;
		default: 
			return DefWindowProc(hWnd,uMsg,wParam,lParam); 
        //То что не надо - передаем системе и она делает работу за нас.

    }

Последний раз редактировалось Stilet; 05.02.2011 в 15:57.
Dimarik вне форума Ответить с цитированием
Старый 18.03.2010, 00:55   #10
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

DWORD это целочисленный тип.

Вообще то по стандарту делают так:

Код:
		case WM_CLOSE:{
			int userEvent = MessageBox(hWnd, "Вы хотите закрыть приложение?", "Выход", MB_YESNO | MB_ICONQUESTION);
			if (IDYES == userEvent)
				DestroyWindow(hWnd);
				}
			break;

		case WM_DESTROY:
			PostQuitMessage(0);
			break;
profi вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Конвертировать формулы из [2007 Word 2007] в [2003 Word 2003] mswmd Microsoft Office Word 8 10.07.2017 17:06
Работать в Word, не открывая документы (работа с закрытыми документами Word) Георгиевич Microsoft Office Word 10 07.09.2009 11:19
Word Maladoj Общие вопросы .NET 5 06.06.2009 09:25
Как вычислять значения вне таблицы WORD, с использованием данных из таблицы WORD prikolist Microsoft Office Word 6 21.11.2008 13:17
Ms Word Farel Общие вопросы Delphi 0 12.01.2008 16:48