Регистрация Главная Пользователи Все разделы прочитаны
Сообщения за день Справка Регистрация
Навигация
Zhyk.org LIVE! Реклама на Zhyk.org Правила Форума Награды и достижения Доска "почета"

Ответ
 
Опции темы
Старый 30.12.2008, 21:30   #1
Заблокирован
 Капитан
Аватар для Ivan_32
 
Ivan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компании
Регистрация: 14.05.2008
Сообщений: 253
Популярность: 1015
Сказал(а) спасибо: 666
Поблагодарили 451 раз(а) в 173 сообщениях
Отправить сообщение для Ivan_32 с помощью ICQ Отправить сообщение для Ivan_32 с помощью Telegram Отправить сообщение для Ivan_32 с помощью Skype™
 
По умолчанию Пишем простое окно на С++


Предполагается что читатель знаком с языком С++ хотя бы на начальном уровне.

Самым сложным при изучении WinAPI наверно является создание элементов управления и самих форм(окон). Все остальное предельно просто и понятно. А тут..тут обычно для новичка много нелогичного и непонятного, но мы попробуем внести логику

Что такое WinAPI в целом? Это набор функций для общения с устройствами операционной системы, это кнопочки если угодно. Вы пишите тот же ShellExecute и по вашей просьбе ОС сделает то что вы ее попросили, в данном случае запустит например что ни будь, это ведь зависит от параметров функции.
--
А вот на этом остановимся. Только что было слышно слово параметры, не правда ли? Точно так же как вы запускаете микроволновку с параметрами , включаете плиту тоже с параметрами, аргументами.
--
Точно так же нужно делать и с WinAPI функциями, на самом деле в каждой такой функции спрятано несколько других. Но не будем увлекатся теорией а перейдем к сути.
--
Создайте в вашей студии проект консольного приложения. Создали ? Хорошо. Теперь подключите h-файлы windows.h (директива #include <windows.h>). Напишите в функции main такую строку.
Код:
MessageBox(0,"Hello world","WinAPI is simple",0);
Запускайте и радуйтесь первому использование функции.
--
Идем дальше. Теперь давайте ознакомимся с каркасом приложения для Windows. Каркасом для него является следующий код:
Код:
#include <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	return 0;
}
Вот это уже полноценное Windows приложение. Разберемся что к чему.
Функция WinMain является заменой привычному main. С нее начинается любая программа. Ее аргументы:
hInstance - хендл на exe-файл из которого запущена программа(или Thread)
hPrevInstance - хендл на что то мистическое, всегда равно нулю.
lpCmdLine и nCmdShow отвечают за командную строку запуска проще говоря параметры с которыми запущена программа если она запущена из CMD.exe или же ярлыком с параметрами.
--
С каркасом разобрались.
Любая программа на WinAPI состоит из нескольких частей.
1. Это графическая часть, нам нужно показать пользователю интерфейс.
2. Это очередь сообщений, мы должны создать цикл обработчик сообщений и функцию для их обработки.
Приступим:

За графическую часть у на отвечает функция CreateWindowEx, она же предоставляет каркас для работы с сообщениями. К слову весь Windows построен на системе сообщений.
Вот она наша функция:
Код:
HWND CreateWindowEx(      
    DWORD dwExStyle,
    LPCTSTR lpClassName,
    LPCTSTR lpWindowName,
    DWORD dwStyle,
    int x,
    int y,
    int nWidth,
    int nHeight,
    HWND hWndParent,
    HMENU hMenu, 
    HINSTANCE hInstance,
    LPVOID lpParam   
);
1. особый дополнительный стиль создаваемого окна, нам пока не нужно.
2. Имя класса, либо нашего либо стандартного класса окна. Используем WC_DIALOG.
3. Заголовок окна.
4. Стиль окна. Тут нам понадобятся два параметра которые между собой обьединяються бинарным OR тоесть символом "|" Эти параметры по своей сути являются битами. Мы используем WS_VISIBLE | WS_SYSMENU.
Первый определяет что наше окно сразу будет видимым при создании, а второй добавляет к окну кнопки close/max/min на рамке, без этого стиля их там не будет.
5. Кордината X на экране. Отсчет кординат идет с верхнего левого угла монитора к нижнему правому.
6. Кордината Y.
7. Ширина окна.
8. Длина окна.
9. Отчество окна, этот параметр применяется для создания кнопочек итд. итп.
10. Уникальный ID нашего окна, что бы различать его в общей очереди сообщений, нам пока не нужно потом ставим ноль.
11. Хендл на модуль нашей программы, можно поставить ноль.
12. Параметр с которым создается окно. Мистический аргумент, я не знаю для чего его можно использовать.

Ну что ж с функцией разобрались. Теперь давайте запустим это. Для нашего окна на понадобится хендл окна типа : HWND.
Добавте код в WinMain:
Код:
HWND hMain=CreateWindowEx(0,WC_DIALOG,"Hello world",WS_VISIBLE | WS_SYSMENU, 500,500,200,200,0,0,0,0);
И запускайте. Вроде бы на экране на миг появилось окно , неправда ли ?
--
Это объясняется тем что у окна нет очереди сообщений, которую мы сейчас добавим. Для начала нам нужен прототип очереди сообщений, иными словами структура. Такой структурой является MSG.
Обрабатывают сообщения с помощью Функций TranslateMessage и DispatchMessage у обоих один аргумент - адрес экземпляра структуры MSG. Но , для начала как нам положить туда эти сообщения? А очень просто. С помощью функции GetMessage:
[CODE]
BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
);
1. Это адрес экземпляра структуры MSG.
2. Хендл на окно для которого будут обрабатываться сообщения, в нашем случае ноль, так как обрабатывать будем сообщения для всей программы.
3 и 4 - это специальные параметры для фильтрации сообщений. Все сообщения это int -число , вот его пороги и задают эти параметры, то есть например от 20 до 40, нам не нужно, так как обрабатывать будем все.
--
Функция проверяет наличие сообщений и в случае наличия возвращает ноль. Нам нужно создать цикл который будет работать пока функция возвращает единицу.

Итак давайте сразу напишем код всей измененной программы:
Код:
#include <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	MSG msg;
	HWND hMain=CreateWindowEx(0,WC_DIALOG,"Hello world",WS_VISIBLE | WS_SYSMENU,CW_USEDEFAULT,CW_USEDEFAULT,200,200,0,0,0,0);
	while(GetMessage(&msg,0,0,0)!=0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}
Предупреждаю. Как только вы запустите вы уже не сможете закрыть ее традиционным способом - только через Диспетчер Задач.
--
Ну думаю все понятно, но я еще раз повторю. Вот видите появился цикл.
Он работает пока GetMessage не возвратит ноль. А пока она возвращает единицу, сообщения переводятся и обрабатываются.
--
Но у нас нет обработчика событий. Функция обработчик событий привязывается к окну а не к msg, вопреки ожиданиям. Тоесть сообщения перенаправляются на функции обработчики, вернее функции обработчики вызываются с сообщением в аргументах.
--
Нам нужно написать функцию обработчик, как же она выглядит:
Код:
LRESULT WINAPI mainProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
//Тут вот будем обрабатывать сообщения.
   switch(message)
  {
  case WM_CLOSE:
         {
          PostQuitMessage(0);
         };break;
  }
}
Много непонятного ? Ничего не страшно. Это каркас функции. На самом деле вам нужна функция которая отвечает ряду требований а именно:
1. Должна иметь вышеуказанные аргументы
2. И должна возвращать вышеуказанный тип - LRESULT.
Остальное ваш код, что хотите то и пишите в нем, и название функции тоже значения не имеет.
В параметр message попадает сообщение - unsigned int==UINT. Как и WS_VISIBLE WC_DIALOG - это константы заданные директивой #define, по сути это числа. Нам нужно определить число WM_CLOSE и написать действие для него. Вот мы его и написали :
PostQuitMessage(0); - заставляет программу закрыться корректным способом, вернув 0 - Sucess.
--
Добавте этот код к вашей программе. Все равно не работает не правда ли?) Это объясняется тем что мы не задали нашему окну обработчик - нашу функцию.
--
Сделать это можно функцией SetWindowLong, это супер пупер функция для работы с параметрами окна, в зависимости от аргументов она делает совершенно разные вещи.
Код:
LONG SetWindowLong(      
    HWND hWnd,
    int nIndex,
    LONG dwNewLong
);
1. Хендл на окно.
2. Индекс значения, в структуре окна.
3. Заменяемое значение.
--
Нам нужно поменть для нашего окна значение DWL_DLGPROC заменить его на адрес нашей процедуры обработчика:
Код:
SetWindowLong(hMain,DWL_DLGPROC,(long)mainProc);
Думаю тут все понятно, если не понятно то сейчас это не критично, главное запомнить как писать каркас приложения.

Ну что ж приведем код уже работающей программы:

Код:
#include <windows.h>
LRESULT WINAPI mainProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	switch(message)
	{
		case WM_CLOSE:
			{
			PostQuitMessage(0);
			};break;
	}
	return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	MSG msg;
	HWND hMain=CreateWindowEx(0,WC_DIALOG,"Hello world",WS_VISIBLE | WS_SYSMENU,CW_USEDEFAULT,CW_USEDEFAULT,200,200,0,0,0,0);
	SetWindowLong(hMain,DWL_DLGPROC,(long)mainProc);
	while(GetMessage(&msg,0,0,0)!=0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}
Продолжение следует

Последний раз редактировалось Ivan_32; 25.01.2009 в 10:24.
  Ответить с цитированием
6 пользователя(ей) сказали cпасибо:
FFForever (31.12.2008), Leo_ня (11.07.2009), Loreg (31.12.2008), Федя (15.07.2009), shagart (07.01.2009), Zhyk (30.12.2008)
Старый 31.12.2008, 00:40   #2
Заблокирован
 Рыцарь-защитник
Аватар для ZliLO
 
ZliLO блестящий пример для подражанияZliLO блестящий пример для подражанияZliLO блестящий пример для подражанияZliLO блестящий пример для подражанияZliLO блестящий пример для подражанияZliLO блестящий пример для подражанияZliLO блестящий пример для подражанияZliLO блестящий пример для подражанияZliLO блестящий пример для подражанияZliLO блестящий пример для подражанияZliLO блестящий пример для подражания
Регистрация: 22.05.2008
Сообщений: 598
Популярность: 2505
Сказал(а) спасибо: 387
Поблагодарили 887 раз(а) в 401 сообщениях
Отправить сообщение для ZliLO с помощью ICQ Отправить сообщение для ZliLO с помощью Skype™
 
По умолчанию

а причем здесь асм и с++?
  Ответить с цитированием
Старый 31.12.2008, 00:57   #3
Заблокирован
 Капитан
Аватар для Ivan_32
 
Ivan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компании
Регистрация: 14.05.2008
Сообщений: 253
Популярность: 1015
Сказал(а) спасибо: 666
Поблагодарили 451 раз(а) в 173 сообщениях
Отправить сообщение для Ivan_32 с помощью ICQ Отправить сообщение для Ivan_32 с помощью Telegram Отправить сообщение для Ivan_32 с помощью Skype™
 
По умолчанию

Раздел С++ сделан для обсуждения решений построенных на особенностях языка, то есть по сути там можно обсуждать работу с указателями нюансы работы с классами - ООП итд , то есть все то что является конструктивно зависимым от языка. А этот гайд больше рассказывает о платформе Win32. С++ взят как более простой язык. Я подумал что на асме будет тяжеловато понять азы.
Но раздел для WinAPI наверно все же стоит отдельный сделать, но это в будущем , сейчас без должного контента и тем более посетителей смысла нет...

Последний раз редактировалось Ivan_32; 09.01.2009 в 11:08.
  Ответить с цитированием
Старый 11.12.2009, 06:53   #4
Заблокирован
 Разведчик
Аватар для Ivan_64
 
Ivan_64 на правильном путиIvan_64 на правильном пути
Регистрация: 23.11.2009
Сообщений: 10
Популярность: 146
Сказал(а) спасибо: 6
Поблагодарили 41 раз(а) в 20 сообщениях
 
По умолчанию Re: Пишем простое окно на С++

PHP код:
#define UNICODE
#include <windows.h>

LRESULT CALLBACK WndProc(HWNDUINTWPARAMLPARAM);

INT WINAPI WinMain(HINSTANCE hInstanceHINSTANCEPSTRINT iCmdShow)
{
   
HWND                hWnd;
   
MSG                 msg;
   
WNDCLASS            wndClass;
   
   
wndClass.style          CS_HREDRAW CS_VREDRAW;
   
wndClass.lpfnWndProc    WndProc;
   
wndClass.cbClsExtra     0;
   
wndClass.cbWndExtra     0;
   
wndClass.hInstance      hInstance;
   
wndClass.hIcon          LoadIcon(NULLIDI_APPLICATION);
   
wndClass.hCursor        LoadCursor(NULLIDC_ARROW);
   
wndClass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
   
wndClass.lpszMenuName   NULL;
   
wndClass.lpszClassName  L"TestWND";
   
   
RegisterClass(&wndClass);
   
   
hWnd CreateWindow(
      
L"TestWND",
      
L"Test Window",
      
WS_OVERLAPPEDWINDOW,
      
CW_USEDEFAULT,
      
CW_USEDEFAULT,
      
320,
      
240,
      
0,0,hInstance,0);
      
   
ShowWindow(hWndiCmdShow);
   
UpdateWindow(hWnd);
   
   while(
GetMessage(&msgNULL00))
   {
      
TranslateMessage(&msg);
      
DispatchMessage(&msg);
   }
   
   return 
0;
}

LRESULT CALLBACK WndProc(HWND hWndUINT message
   
WPARAM wParamLPARAM lParam)
{

   switch(
message)
   {
   case 
WM_DESTROY:
      
PostQuitMessage(0);
      return 
0;
   default:
      return 
DefWindowProc(hWndmessagewParamlParam);
   }

Вот это более кавайный пример. Тут создается свой класс окна что гораздо правильней чем юзать диалоговый.
  Ответить с цитированием
Ответ

Метки
с++, winapi, windows

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
пишем разными цветами (скрипт) Hummel Читы, баги и статьи по WoW 4 13.06.2010 00:22
2 и более окон FallenAngel Rising Force Online 5 30.11.2008 14:29
[Руководство] Пишем иньектор DLL-ок на С++. Ivan_32 ASM/WinAPI 0 30.11.2008 00:31
Пишем сразу нескольким игрокам, конференц общение без пати. Danilk Rising Force Online 7 25.06.2008 23:19

Заявление об ответственности / Список мошенников

Часовой пояс GMT +4, время: 03:49.

Пишите нам: [email protected]
Copyright © 2024 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net