| 
	
		
		
			| Tutorial [EN/RU]: создание окна приложения, WinAPI |  |  |  | 
| WXZRW | Дата: Суббота, 08 Августа 2009, 16:15 | Сообщение # 1 |  |   Thousand faces conspiration Сейчас нет на сайте | Последнее обновление 09/08/2009  Решил выложить сейчас, в принципе, код откомментирован на английском, но прочие обьяснения пока что будут на русском, а потом я добавлю и на английском. Сам туториал очень простой, без использования OpenGL или DirectX, чтобы не возникало дополнительных сложностей, поскольку все это в принципе предназначено для самых новичков, если вы уже обладаете такими знаниями, то дальше можете не читать.   Ну и также сперва предупреждение : любая информация которая здесь предоставлена, может содержать те или иные неточности, код может не компилиться при некоторых условиях. Все что здесь есть, предоставлено мною без каких-либо гарантий и ответственности, и я не несу никакой ответственности за любой возможный ущерб, который может быть вызван использованием любой части данного поста, кода или информации в любом виде и при любых обстоятельствах.   Далее код и инфа по коду :    Code #include <windows.h> 
 // Declare some variables and function prototypes for further usage
 
* Сперва обьявим функции и переменные :
  Первые три вещи это контекст устройства (device context), хендл окна (window handle), и инстанс приложения (application instance) 
 Code  HDC dc;
 
 HWND w_handle;
 HINSTANCE inst;
 
 LRESULT CALLBACK w_process(HWND wnd_handle,UINT system_msg,WPARAM w_param,LPARAM l_param);
 
 WPARAM _process(HWND w_handle);
 
 // Below functions we need
 * Главная функция, здесь устанавливаем все настройки и создаем окно, также как и класс приложения. Точнее, это точка входа в приложение.    Code // Main function int WINAPI WinMain(HINSTANCE inst,HINSTANCE prev_inst,LPSTR line,int show)
 {
 // We want window styles at first
 
 DWORD ex_style;
 DWORD style;
 
 // We 'll need it later to set up window size and position.
 
* Сперва создадим структуры для класса и для окна, заполним их переменными и создадим класс.
   Code RECT rect; 
 // And at last we need to set a window class
 
 WNDCLASSEX w_class;
 
 // Allocate memory for class structure
 
 [b]* Выделим память под структуру класса[/b]
 
 memset(&w_class,0,sizeof(WNDCLASSEX));
 
 // Set up class variables below
 
* Параметры переменных класса, лучше всего посмотреть инфу на MSDN по структуре WNDCLASSEX, поскольку тут могут быть варианты, то есть в данном случае я использовал одни параметры, но в других случаях могут быть использованы и другие параметры.
  * Дополнительно : этот параметр (hbrBackground) может быть определен как NULL, в таком случае окно не будет закрашено. Многие авторы (особенно те кто пишет туториалы под OpenGL/DirectX) не утруждаются этим, но я задал черный цвет.    Code w_class.cbClsExtra = 0; // extra bytes, we want it to be 0 w_class.cbSize = sizeof(WNDCLASSEX); // size of the whole structure
 w_class.cbWndExtra = 0; // yet another extra bytes, shulda be 0 in our case
 w_class.hbrBackground = (HBRUSH)(COLOR_WINDOW+2); // set up background color, it 'll be black.
 //if you want it to be white, set +1 instead +2 then
 w_class.hCursor = LoadCursor(NULL,IDC_ARROW); // we 'll set standard cursor, but you can set your own one
 w_class.hIcon = LoadIcon(NULL,IDI_APPLICATION); // standard icon, but culda be NULL instead of it also
 w_class.hIconSm = LoadIcon(NULL,IDI_WINLOGO); // same as above
 w_class.hInstance = inst; // handle to instance
 w_class.lpfnWndProc = w_process; // pointer to window procedure
 w_class.lpszClassName = "test"; // class name
 w_class.lpszMenuName = NULL; // menu name, but if set to NULL, window have no default menu then
 w_class.style = CS_HREDRAW | CS_VREDRAW; // set class style(s)
 
 // After class infromation is OK and available, it's time to register the class
 * Когда все параметры класса заданы, можно его зарегистрировать в системе, но не наоборот.    Code RegisterClassEx(&w_class); 
 // Window styles below
 
 style = WS_OVERLAPPEDWINDOW;
 ex_style = WS_EX_APPWINDOW;
 
 // Window rect to set window size (width and height), and window position (left and top)
 // Note that 0,0 yields a top left corner of the screen
 * Теперь можем приступать к созданию окна, для начала надо задать позицию окна на экране и размеры окна.   * Дополнительно : left и top это координаты верхнего левого угла окна, у нас это точка отсчета коодинат экрана, то есть начало координат 0,0 это верхний левый угол экрана    Code rect.bottom = 480; rect.left = 0;
 rect.right = 640;
 rect.top = 0;
 
 // Before creating the window we also need to set up window rectangle and style
 * После того как структура заполнена, вызываем функцию AdjustWindowRect чтобы применить все параметры, которые были заданы.   * Дополнительно : эта функция используется перед созданием окна, если окно уже создано, то для изменения параметров RECT нужно использовать функцию SetWindowPos    Code AdjustWindowRect(&rect,style,FALSE); // This one only valid before window is created, to change rect of existing window // you shulda be using SetWindowPos function from WinAPI
 
 // Ok, we're ready to create it
 * Создаем само окно, опять же рекомендую смотреть в MSDN какие здесь именно параметры вообще могут быть.    Code w_handle = CreateWindowEx( ex_style, // window style (extended), we had to set up before
 "test", // class name
 "Test", // window name
 style, // yet another window style
 0, // horisontal window position
 0, // vertical window position
 rect.right - rect.left, // window width
 rect.bottom - rect.top, // window height
 NULL, // handle for parent window, it's NULL 'coz we have no such window
 NULL, // handle for menu, it's NULL as well
 inst, // handle to instance
 NULL); // Additional info, but we don't want it at all, so it's NULL too
 
 // Now let's set window position as well, but note it ain't really necessary, if we 'll skip this, window 'll
 // be applied to the top left of screen
 * Эту функцию можно и не вызывать, я делаю это чтобы показать, как изменить положение окна. Вообще при этом должно быть обработано соответствующее системное сообщение в нашей функции w_process, но для простоты я этого не стал делать, тем более что двигаем окно в самом
 начале перед его созданием.
  * Дополнительно : мы здесь не изменяем размер окна, только позицию. Поэтому последний параметр у нас SWP_NOSIZE, два предыдущих параметра также NULL. Если нужно изменить размер окна, тогда размеры нужно указать вместо NULL и также изменить последний параметр.    Code SetWindowPos( w_handle, // window handle
 HWND_TOP, // how it shulda behave, we wanna it on the top of
 240, // where the left side shulda be
 320, // same for top, note both variables given in client coords
 NULL, // specify new width of the window
 NULL, // same for height, this one and above shulda be given in pixels, but note we don't want it that way
 SWP_NOSIZE); // 'coz we want 2 items we have above to bee ignored, we set NOSIZE to remain window as it is
 
 // We now want to set up window show state
 
* Теперь задаем стэйт окна, в данном случае все оставляем как есть по умолчанию, но можно и другой параметр указать, например SW_SHOWMAXIMIZED, тогда окно будет развернуто на весь экран.
   Code ShowWindow(w_handle,SW_SHOW); // window handle and yet another param to make our window active * Показываем курсор мыши, или можно его убрать, тогда пишем false    Code ShowCursor(true); // show mouse cursor too, if no longer required it culda be set to FALSE then 
 UpdateWindow(w_handle); // update window
 
 return _process(w_handle); // return result back to, after it's handled by _process function
 }
 * Здесь отслеживаем системные сообщения и обрабатываем их. Опять же, советую смотреть в MSDN по поводу сообщений.
   Code // Shulda be declared within the class in WinMain function LRESULT CALLBACK w_process(HWND w_handle,UINT _msg,WPARAM wparam,LPARAM lparam)
 {
 LONG lret = 0;
 
 // Below we need to handle system messages, but we only take care about WM_CLOSE
 
* Обрабатываем только WM_CLOSE, остальные сообщения игнорируем и передаем дальше
   Code switch(_msg) {
 
 case WM_CLOSE : // Exit from application if WM_CLOSE command incoming
 {
 
* Если поступило сообщение о закрытии окна, тогда удаляем из памяти device context и класс
   Code ReleaseDC(w_handle,dc); // Release device context from memory 
 UnregisterClass("Test",inst); // Remove our class too
 
 PostQuitMessage(0); // Kill application
 }
 break;
 
 default :
 
* Те сообщения, которые мы здесь не обработали, обрабатываются по умолчанию
   Code lret = DefWindowProc(w_handle,_msg,wparam,lparam); // Default processing for all the messages not processed by // our application, to make sure that all the messages are processed anyway.
 
 break;
 }
 
 return lret;
 }
 
* Ну и здесь главный цикл приложения, беконечный
   Code // We will pass window handle to this one in WinMain function (at the end of) WPARAM _process(HWND w_handle)
 {
 MSG msg;
 
 // This one is the main application loop, it's infinite.
 
 while(1)
 {
 
* Обрабатываем системные сообщения
   Code if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Dispatch system messages {
 if(msg.message == WM_QUIT) break; // If got WM_QUIT message then break the loop and exit from application
 
 TranslateMessage(&msg);    // Otherwise, let's find out what the message is exactly
 DispatchMessage(&msg); // And execute it
 
 // Here we culda have an else statement and some stuff inside of it, for example, scene rendering, but we leave
 // it as is, 'coz we have nothing to do at this time.
 
* Здесь можно было бы рендерить сцену, но так ее попросту нет, то ничего не делаем.
   Code } }
 
 return(msg.wParam);
 }
 
Также прикладываю и .cpp исходник, для компиляции в Visual C++ нужно создать проект типа Win32 Application.
  Ну и если нужно больше по-русски, то пишите запросы, хотя я позже планирую дописать еще инфы здесь. Следующий туториал будет о подключении OpenGL. |  |  |  |  |  | 
| nilrem | Дата: Суббота, 08 Августа 2009, 16:36 | Сообщение # 2 |  |   Просветленный разум Сейчас нет на сайте | WXZRW Извини, но это пока не туториал, а просто исходный код с комментариями и ничего больше.
 Что такое HDC, HWND, HINSTANCE и т.д.?
 Вот если ты и об этом вкратце упомянешь, и разложишь по полкам, то тогда это и будет туториал. Сам же сказал, что для новичков, поэтому код нужно обьяснить.
 Иначе получается обыкновенный копипаст и ноль приобретенных знаний.
  ТО, ЧТО ТЕБЕ КАЖЕТСЯ ЕСТЕСТВЕННЫМ, ДЛЯ ДРУГИХ ТЕМНЫЙ ЛЕС. 
 
 Сообщение отредактировал nilrem - Суббота, 08 Августа 2009, 16:41 |  |  |  |  |  | 
| WXZRW | Дата: Суббота, 08 Августа 2009, 16:41 | Сообщение # 3 |  |   Thousand faces conspiration Сейчас нет на сайте | Quote (nilrem) Извини, но это пока не туториал, а просто исходный код с комментариями и ничего больше. Что такое HDC, HWND, HINSTANCE и т.д.?
 ОК, тогда надо будет дописать обьяснения по структурам. Хотя если честно, зарубежные авторы обычно не стесняются назвать туториалом 10 строк для отрисовки кубика на OpenGL =)   На самом деле, ты все верно говоришь, вот поэтому тоже на форуме я тему создал, а не в статьях, чтобы кому надо, здесь спросили бы. |  |  |  |  |  | 
| 777OLEKSEY777 | Дата: Вторник, 11 Августа 2009, 16:35 | Сообщение # 4 |  |   Руководитель и 3D дизайнер в IlluGameTea Studio Сейчас нет на сайте | WXZRW, спасибо. Думаю начинающим программерам пойдет   |  |  |  |  |  | 
| GC-Vic | Дата: Вторник, 11 Августа 2009, 23:57 | Сообщение # 5 |  |   GcUp.ru Сейчас нет на сайте | WXZRW, используй тэг "code". Вот так:   Code if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Dispatch system messages {
 if(msg.message == WM_QUIT) break; // If got WM_QUIT message then break the loop and exit from application
 
 TranslateMessage(&msg); // Otherwise, let's find out what the message is exactly
 DispatchMessage(&msg); // And execute it
 
 // Here we culda have an else statement and some stuff inside of it, for example, scene rendering, but we leave
 // it as is, 'coz we have nothing to do at this time.
 Закон Мерфи: "Если вы уверены, что ваш поступок встретит всеобщее одобрение, кому-то он обязательно не понравится".
 |  |  |  |  |  | 
| WXZRW | Дата: Четверг, 13 Августа 2009, 14:00 | Сообщение # 6 |  |   Thousand faces conspiration Сейчас нет на сайте | Quote (GC-Vic) WXZRW, используй тэг "code". ОК, сегодня попозже обновлю тему. |  |  |  |  |  | 
| anisimov | Дата: Четверг, 13 Августа 2009, 20:21 | Сообщение # 7 |  |   старожил Сейчас нет на сайте | HDC, HWND, HINSTANCE дескрипторы контекста устройства. Характерно для WinApi. HWND дескриптор контекста окна. Вот же сказано.  Первые три вещи это контекст устройства (device context), хендл окна (window handle), и инстанс приложения (application instance) 
 http://vkontakte.ru/id56359373
 Строю Город, обустраиваю Остров. Присоединяйтесь.
 |  |  |  |  |  | 
| WXZRW | Дата: Четверг, 13 Августа 2009, 21:31 | Сообщение # 8 |  |   Thousand faces conspiration Сейчас нет на сайте | Quote (anisimov) HDC, HWND, HINSTANCE дескрипторы контекста устройства. Характерно для WinApi. HWND дескриптор контекста окна. Вот же сказано.   Первые три вещи это контекст устройства (device context), хендл окна (window handle), и инстанс приложения (application instance)  Да, теперь все ОК, я уже после того как nilrem обратил на это внимание, дописал данную фразу, до этого я об этом не упоминал, (ну имхо читатели сами в MSDN бы глянули, не проблема). |  |  |  |  |  | 
| vergil010 | Дата: Пятница, 14 Августа 2009, 23:00 | Сообщение # 9 |  |   3D master Сейчас нет на сайте | WXZRW, добавил тэги =) если не сложно, добавляй их сразу, при написаниии статьи. 
 skype: vergil010
 |  |  |  |  |  | 
| WXZRW | Дата: Суббота, 15 Августа 2009, 13:58 | Сообщение # 10 |  |   Thousand faces conspiration Сейчас нет на сайте | Quote (vergil010) WXZRW, добавил тэги =) если не сложно, добавляй их сразу, при написаниии статьи.  ОК, благодарю! Вообще-то думал как выделить код, только вот тега не заметил :) В смысле, до того, как GC-Vic обратил на это мое внинмание. Ну, новый тутор постараюсь оформить в лучшем виде. |  |  |  |  |  | 
| vergil010 | Дата: Суббота, 15 Августа 2009, 15:10 | Сообщение # 11 |  |   3D master Сейчас нет на сайте | WXZRW, ок, будем ждать. Очень интересный тутор! 
 skype: vergil010
 |  |  |  |  |  | 
| Женек | Дата: Четверг, 15 Июля 2010, 20:24 | Сообщение # 12 |  |   частый гость Сейчас нет на сайте | скачал твой код вставил вот ошибка что у меня не так( код один в один)  Ошибка	1 error C2440: =: невозможно преобразовать 'const char [5]' в 'LPCWSTR' 
 
     |  |  |  |  |  | 
| WXZRW | Дата: Пятница, 16 Июля 2010, 15:10 | Сообщение # 13 |  |   Thousand faces conspiration Сейчас нет на сайте | Quote (Женек) скачал твой код вставил вот ошибка что у меня не так( код один в один)   Ошибка 1 error C2440: =: невозможно преобразовать 'const char [5]' в 'LPCWSTR'  Мда, давно уже не был на форуме...   Код компилил на VC++ 6.0 Standard, поэтому на более новых версиях может не компилиться. Впрочем, как я понял, тебе уже в другой теме показали как исправлять эту ошибку. |  |  |  |  |  
 |