
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.217.2] |
![]() |
|
Сообщ.
#1
,
|
|
|
сперва сам код vs6, dev
![]() ![]() #include <windows.h> HINSTANCE hInst; ATOM MainWindowClass(HINSTANCE hInstance); int MasterWindow(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK WndProc( HWND hWnd,//ДЕСКРИПТОР ОКНА UINT message,//код сообщения WPARAM wParam, LPARAM lParam//32 bit ) { switch (message) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg;// Объявление структуры типа MSG, для работы с сообщениями// код текущего сообщения MainWindowClass(hInstance); if (!MasterWindow (hInstance, nCmdShow)) { return FALSE; } while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } ATOM MainWindowClass(HINSTANCE hInstance) { WNDCLASSEX wc; // memset(&wc,0,sizeof(wc)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc;//функция обратного вызова wc.lpszClassName = "aaaaWndClass"; wc.hInstance = hInstance; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground= (HBRUSH)COLOR_APPWORKSPACE;//ТЕМНЫЙ wc.lpszMenuName = NULL; wc.hIconSm = NULL; return RegisterClassEx(&wc);// Создаем и регистрируем оконный класс } int MasterWindow(HINSTANCE hInstance, int nCmdShow) { HWND MainHWND;// Уникальный идентификатор главного окна приложения(handle) hInst = hInstance; /* Сохраняем идентификатор приложения*/ // Преверяем, не было ли это приложение запущено ранее MainHWND = FindWindow ( "aaaaWndClass", /* указатель на имя класса*/ NULL/*указатель на имя окна*/); if(MainHWND) { // Если окно приложения было свернуто в пиктограмму, восстанавливаем его if(IsIconic(MainHWND)) ShowWindow(MainHWND, SW_RESTORE); SetForegroundWindow(MainHWND); return FALSE; } MainHWND = CreateWindow( "aaaaWndClass", "NULL", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,//координаты по вертмкали CW_USEDEFAULT,//координаты по горищонатли CW_USEDEFAULT,//гирина CW_USEDEFAULT,//высота MainHWND, /* дескриптор родительского окна */ (HMENU)NULL,//дескриптор меню (HINSTANCE)hInstance, // Идентификатор приложения NULL); if (!MainHWND) { return FALSE; } ShowWindow(MainHWND, SW_SHOWMAXIMIZED); UpdateWindow(MainHWND); return TRUE; } 1? HINSTANCE и HWND чем они отличаются? HWND- это, как понял индивидуальный номер(ID) окна,фрейма,кнопки и т.д. HINSTANCE -это описание созданного обьекта-дескриптор(окна,фрейма,кнопки)-всё что входит CreateWindow и ATOM(класс окна), тогда почему они все видут к одному определению (идти к определению HINSTANCE)->DECLARE_HANDLE(HINSTANCE);-> ![]() ![]() #ifdef STRICT typedef void *HANDLE; [B]#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name[/B] #else typedef PVOID HANDLE; #define DECLARE_HANDLE(name) typedef HANDLE name #endif /////////////////////////////////////// HWND (идти к определению HWND)-> ![]() ![]() #ifndef WIN_INTERNAL [B]DECLARE_HANDLE (HWND)[/B]; DECLARE_HANDLE (HHOOK); #ifdef WINABLE DECLARE_HANDLE (HEVENT); #endif #endif -> ![]() ![]() #ifdef STRICT typedef void *HANDLE; [B]#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name[/B] #else typedef PVOID HANDLE; #define DECLARE_HANDLE(name) typedef HANDLE name #endif ?1б дескриптор-это HINSTANCE, хендл(HANDLE) - это HWND не русские слова тяжело врезается в голову и с чем это ассоциировать? ![]() из разных книг Цитата 1)Этот дескриптор содержит адрес начала кода программы в ее адресном пространстве. 2)Дескриптор hInstance чаще всего требуется функциям, работающим с ресурсами программы. 3)...дескриптор модуля — то это указатель. Дескриптор файла — это индекс... 1) в ее адресном пространстве -чего? памяти 2) работающим с ресурсами программы -если я не использую ресурсы -то не нужно- как на это реагировать ![]() 3)...дескриптор модуля — то это указатель.Дескриптор файла — это индекс... наверное имеется ввиду это #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name вот эту строчку мне надо поподробней и понять (разжевать)на простых примерах, как это работает ?№2 для чего нужна глобальная переменная HINSTANCE hInst(дурацкий вопрос!!!); ели глобальные переменные зло, как от нее избавиться(я с ней помучался)я сейчас сам на него отвечу.Но не понимаю почему это работает (во многих книгах,руководств по созданию главного окна) что она нужна... убрать глобальную переменную и убрать реализацию в //hInst = hInstance; /* Сохраняем идентификатор приложения*/ ?3 чем отличается Compile(ctrl +F7) и build(F7) ?4 если разбить как здесь разбивка исходника на 2 файла то ошибки не появляются типа: I:\VS 6\a\aaaaaaaa\main.c(27) : warning C4100: 'lpCmdLine' : unreferenced formal parameter I:\VS 6\a\aaaaaaaa\main.c(27) : warning C4100: 'hPrevInstance' : unreferenced formal parameter I:\VS 6\a\aaaaaaaa\main.c(69) : warning C4100: 'nCmdShow' : unreferenced formal parameter это глюк VS6 (Warning level -Level 4-уровень проверок на ошибки) ?5 что лучше в плане скорости приложения ваше мнение и личный опыт я делаю прогу подобее notepad++(зачем для себя) ![]() ![]() while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // или while (TRUE) { if (PeekMessage(&msg,NULL,0,0, PM_REMOVE) ==TRUE) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } } Цитата Если функция GetMessage() обнаруживает в очереди сообщение WM_QUIT (код 0x12), то она завершается с возвратом значения FALSE, что приводит к завершению цикла и переходу на предложение return Msg.wParam; т.е. к завершению главной функции и всего приложения. Если функция GetMessage() не обнаруживает сообщений в очереди потока, система останавливает выполнение данного потока и переводит его в «спящее» состояние. Такое состояние потока не потребляет процессорного времени и не тормозит работу системы. Поток возобновит свою работу, как только в очереди появится сообщение. //GetMessage ждет сообщение и выходит только, если окно получило сообщение. // PeekMessage выходит сразу в не зависимости от того есть сообщение или нетВместо функции GetMessage() часто используют функцию PeekMessage(), которая имеет следующий прототип: BOOL PeekMessage ( LPMSG lpMsg, //адрес структурной переменной с сообщением HWND hWnd, //дескриптор окна UINT wMsgFilterMin, //Min номер выбираемого сообщения UINT wMsgFilterMax, //Max номер выбираемого сообщения UINT wRemoveMsg //флаг удаления сообщения ); Первые четыре параметра функции PeekMessage() совпадают с параметрами функции GetMessage(). Пятый параметр wRemoveMsg определяет, как должно быть выбрано сообщение из очереди, а именно: • PM_NOREMOV – сообщение выбирается и не удаляется из очереди; • PM_REMOV – сообщение выбирается и удаляется из очереди. • Функция PeekMessage()не ждет,когда сообщение поступит в очередь сообщений,а сразу возвращает управление. Если сообщения в очереди нет,то функция возвращает нуль, а если сообщение находится в очереди, оно помещается в структурную переменную типа MSG и удаляется из очереди сообщений (флаг PM_REMOV) или не удаляется (флаг PM_NOREMOV). • Функция PeekMessage() часто используется для оптимизации работы программы. Если сообщение не находится в очереди сообщений, то в свободное время можно выполнять какую-либо другую работу. Этот прием часто встречается в программах, выполняющих графическую анимацию, и более эффективен, чем использование сообщений от таймера. ?6 typedef -нужен для того, чтобы дать другое имя, для чего? что легче читать, что сам написал или зарезервированы для того чтобы не произошел бзод, если везде понаставить int, short, __stdcall, то нормально работает или есть какое-то соглашение(условие) для стабильности проги и компиляции? ![]() ![]() typedef WORD ATOM; typedef unsigned short WORD; #define WINAPI __stdcall typedef unsigned int UINT; typedef UINT WPARAM; typedef LONG LPARAM; ?7 ![]() ![]() LRESULT CALLBACK WndProc( HWND hWnd, UINT message,//код сообщения WPARAM wParam, LPARAM lParam//32 bit ) UINT message,//это код сообщения или идентификатор сообщения ?8в vs6 сам добавляется файл basetsd.h для чего он образуется ? почему он сам ставиться? для чего он нужен? его нету в проекте dev и codeblock! спасибо всем кто ответит наболевшие вопросы любознательность это порог? или любо знать |
Сообщ.
#2
,
|
|
|
№1. Грубо говоря, HWND - Одно из ваших окон, а HINNSTANCE - ваше приложение=программа. А ведут они "к одному" потому, что и то и другое - скрытые(=скрываемые разработчиками Винды) от пользователя структуры.
|
Сообщ.
#3
,
|
|
|
Цитата ?3 чем отличается Compile(ctrl +F7) и build(F7) Compile - это компиляция одной единицы build - это компиляция всего проекта Цитата ?5 что лучше в плане скорости приложения ???!!!!!!!!?????????!!!!! Цитата ?6 typedef -нужен для того, чтобы дать другое имя, для чего? Не дать другое имя а переопределить объект. Цитата понаставить int, short, __stdcall, то нормально работает или есть какое-то соглашение(условие) для стабильности проги и компиляции? Соглашения об вызовал можно и не ставить у каждого компилятора уже в настройках проставлено, нужно если твой модуль будет общаться с другими модулями. Цитата UINT message,//это код сообщения или идентификатор сообщения Да без разницы. Ты привел синонимы. Цитата ?8в vs6 сам добавляется файл basetsd.h для чего он образуется ? почему он сам ставиться? для чего он нужен? его нету в проекте dev и codeblock! Чтобы тебе не нужно было ручками добавлять. Во всех IDE по разному. |
Сообщ.
#4
,
|
|
|
№2: hInstance бывает нужна дабы загрузить себе картинку курсора, иконку, ... из такого-то приложения. Но её, переменную, в принципе всегда можно и откопать, а не хранить и молиться на неё.
№3 - вопрос не по API, а по среде. Вкратце: компиляция - создание OBJ-ей, а Build-строит, т.е. компилирует и компонует:compile+link. |
Сообщ.
#5
,
|
|
|
Цитата 1? HINSTANCE и HWND чем они отличаются? В итоге они там все сведутся к типу PVOID |
Сообщ.
#6
,
|
|
|
№5: для проги типа "notepad++" лучше (без гемора) писать с GetMessage.
Добавлено Цитата Dem_max @ Это ж раньше, кажись, было. Сейчас все сводятся к этакому формальному отсыланию к структуреВ итоге они там все сведутся к типу PVOID ![]() ![]() struct { int unused; }; |
Сообщ.
#7
,
|
|
|
Цитата Сейчас все сводятся к этакому формальному отсыланию к структуре Какая там внутри структура не известно, известно взять хотя бы исходники Win2000 но в итоге какой нить HWND это указатель на структуру в недрах винды |
Сообщ.
#8
,
|
|
|
Цитата Dem_max @ Согласен. Раньше лучше было: неизвестно и всё, а сейчас так и тянет сунуться и узнать чему же равно это значение unused ?.. ;-) Какая там внутри структура не известно, известно взять хотя бы исходники Win2000 но в итоге какой нить HWND это указатель на структуру в недрах винды Добавлено Цитата grat1 @ Не дурацкий, а нормальный вопрос. И она ничуть не глобальная, а локальная для WinMain'а.HINSTANCE hInst(дурацкий вопрос!!!); ели глобальные переменные зло, как от нее избавиться Цитата grat1 @ Если б вы учились в кулинарном техникуме, то это была бы любознательность; а так - вам же для дела надо (для блокнота++). любознательность это порог? или любо знать |
Сообщ.
#9
,
|
|
|
Цитата grat1 @ ?5 что лучше в плане скорости приложения В плане скорости - без разницы. Но приведенный вариант кода с PeekMessage никуда не годится, т.к. при отсутствии сообщений этот цикл будет работать в холостую, попусту занимая\раскаляя процессор и не давая работать другим потокам\процессам (включая фоновые системные потоки обнуления страниц памяти, записи на диск и т.п.). Поэтому циклы с PeekMessage обычно используются с веткой if .. else - когда больше нет сообщений в очереди выполняется некая функция фоновой обработки (типа OnIdle - действия при простое) и затем вызывается ф-я WaitMessage для усыпления потока до прихода нового сообщения. В итоге связка PeekMessage + WaitMessage работает также как и GetMessage, но при этом позволяет выполнить некие действия перед тем, как поток уснет в ожидании нового сообщения. |
Сообщ.
#10
,
|
|
|
Цитата grat1 @ 1? HINSTANCE и HWND чем они отличаются? ... почему они все видут к одному определению ... не русские слова тяжело врезается в голову и с чем это ассоциировать? В переводе на русский Handle - это "ручка\рычаг управления" чем либо. Обычному пользователю незачем знать все потроха внутреннего устройства сложных объектов, будь то бытовая техника, автомобиль, самолет или объект операционной системы - везде рулит принцип инкапсуляции, когда все внутренние потроха скрываются за капотом "черного ящика", а наружу для пользователя выводятся только "хэндлы" - ручки\кнопки\рули управления. Да, в винде для простоты и унификации практически все хэндлы сводятся к типу PVOID, но это ни о чем не говорит, т.к. из соображений "безопасности" только приватным данным процесса даются хэндлы, представляющие собой прямой указатель на структуру данных (HINSTANCE, HMODULE, HGLOBAL, хэндл кучи и т.п.). А хэндлы общесистемных объектов обычно представляют собой индексы различных таблиц. Например, HWND, HMENU и т.п. это индексы таблицы описателей объектов оконной подсистемы win32, которая мапится\проецируется в user32.dll. Но все это "внутренние потроха" ОС, которые обычным юзерам (не "кулхацкерам" ![]() PS: Иногда вместо слова "хэндл" используется слово "дескриптор". Но логически это не совсем верно, т.к. под дескриптором (описателем) обычно понимается некая структура, описывающая объект. А хэндл это просто некое число (указатель, индекс, ID), по которому можно получить доступ к этой структуре |
Сообщ.
#11
,
|
|
|
Цитата grat1 @ HINSTANCE и HWND чем они отличаются? HWND- это, как понял индивидуальный номер(ID) окна,фрейма,кнопки и т.д. HINSTANCE -это описание созданного обьекта-... Это типы производные от указателя. Также как и самые разнообразные другие "хэндлы". Отличаются по их назначению и применению. Чтобы не путать различные указатели между собой, определены различные типы. После этого их применение может контролировать компилятор, который сразу указывает на возможные ошибки. Кстати, HINSTANCE - это фактически адрес загрузки модуля в память. Обычно равен 0x400000. |
Сообщ.
#12
,
|
|
|
Cпасибо всем!!!
У меня еще вопросы. ![]() ![]() wc.cbSize = sizeof(WNDCLASSEX)////размер структуры в байтах; ?№1 зачем измерять, подчитывать размер класса, для чего и какая от него польза? ?№2 как создаются 64bit-ные окна, я так понял в моем примере они 32bit-ные, и есть ли смысл создавать и создвать для моего блокнота(в дальнейшем переделаю под ide, но это пока мечты),заранее правельно спроектированный проект залог меньшего гемора. ?№3 у меня будет мульти язычная прога. ASCII или сразу на unicode(читал много гемора с ASCII ) размер проги играет роль вот поэтому перешел на Си(асм - не потяну ![]() //Чтение много язычного интерфейса через *.ini, когда весь проект будет переведен -> *.dll ?№4 ![]() ![]() HINSTANCE hPrevInstance//дескриптор предыдущего экземпляра приложения ?№5 генератор кода под Win32api Cи, нашел только VISG: visual and smart GUI builder v.095, если ещё подобные без редакторов ресурсов. |
Сообщ.
#13
,
|
|
|
№1: система так может понимать какую версию её функционала вы используете. Пишут, что сие часто.
№2: в среде задаются тип сборки (win32/win64) и всё делает сам компилятор/компоновщик. №3: вопрос непонятно в чём. Но если что, то бесспорно пора на уникод переходить. Всё-таки 21 век... №4: да, используется. Есть редкие функции, коим надо. Скажем, создание окна вручную. |
Сообщ.
#14
,
|
|
|
Цитата grat1 @ №4 HINSTANCE hPrevInstance//дескриптор предыдущего экземпляра приложения читал -это атрофия было прошолого Да, это пережитки времен Win16 (как и само понятие HINSTANCE), поэтому в Win32 hPrevInstance всегда = NULL, а HINSTANCE по смыслу и значению совпадает с HMODULE (хэндл исполняемого модуля = базовому адресу его загрузки\маппинга в память) См.популярное чтиво - тыц, тыц |
![]() |
Сообщ.
#15
,
|
|
Про HWND тоже было: Список окон
|