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, поэтому на более новых версиях может не компилиться. Впрочем, как я понял, тебе уже в другой теме показали как исправлять эту ошибку.
|
|
| |
|