Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Начинающим, изучать WinAPI 
:(
    Опции темы
Fixin
Дата 25.8.2005, 20:38 (ссылка) |    (голосов:6) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 8
Всего: 18



Windows API.
Введение.
Это не книга, не учебник. Это статья, призванная помочь Вам в изучении Windows API на языке C/C++, но не учит языку. Многие программы написаны с использованием макросов, описанных в заголовочном файле <WindowsX.h>.
Начало.
Многие, начинающие изучать API (application programming interface – интерфейс программирования приложений), удивляются объему кода, сложности и тп, говорят, что проще сделать в Borlan® Builder®. Если Вы так думаете, то зачем читаете этот текст?
Вы еще здесь? Тогда продолжим серьезно и без лени.
Вот простейший код:
Код 1.0+NoWindow.cpp+------------------------------------------------
Код

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
    MessageBox(NULL, "Сказала собака баскервилей.", "Ну, здравствуй, Герасим.", MB_OK|MB_ICONEXCLAMATION);
    return 0;
}

Код 1.0+NoWindow.cpp+------------------------------------------------Конец
Что за прараметры?
Начнем с параметров главной функции. Кстати, это САМАЯ главная функция. Функция WndProc (о которой позже) является главной оконной процедурой.
Итак, параметры… HINSTANCE вообще интересный тип. Это своего рода дескриптор объекта (HANDLE).
В первом случае (hInstance) он указывает на тот исполняемый модуль, на основе которого запущен процесс данного кода. Проще говоря, указывает на файл “NoWindow.exe”.
Второй параметр (hPrevInstance) – пережиток Win16. В 32-разрядных приложениях не используется. Раньше обозначал предыдущий запущенный экземпляр данного приложения. Если не ноль, значит Бог есть! Однозначно.
Третий (lpszCmdParam) – строка параметров, которые были посланы программе при запуске. Если их не было, то строка пуста.
Четвертый (nCmdShow) – число, обозначающее вид окна при запуске. Например, свернутое, развернутое, нормальное.
Если решили изменить состояние окна во время выполнения приложения, то это сообщение посылается в окно функцией ShowWindow, например так:
Код

ShowWindow(hwnd, SW_SHOWMINIMIZED);


За одно, разберем параметры вызова MessageBox.
Первый – дескриптор окна, к которому принадлежит сообщение. Это нужно для того, что бы Windows знала, какое окно его вызвало и, соответственно, сделать его неактивным, пока вы не ответите в нем нажатием какой-нибудь кнопки.
Второй и третий – строки. Соответственно, текста сообщения и текста заголовка сообщения.
Четвертый – самый интересный. В нем указывается стиль сообщения. Они находятся в файле <WinUser.h>. Смотрите MSDN.
Делаем окно.
Начнем сразу с кода:
Код 2.0+SimWnd.cpp+------------------------------------------------
Код

#include <windows.h>
#include <windowsx.h>

#define SimWnd_DefProc DefWindowProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL Register(HINSTANCE hInstance);
HWND Create(HINSTANCE hInstance, int nCmdShow);

static char szAppName[] = "SimWnd";
static HWND hMainWindow;

void SimWnd_OnDestroy(HWND hwnd);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpszCmdParam, int nCmdShow)
{
    MSG Msg;

    if (!Register(hInstance))
            return FALSE;    
    if (!Create(hInstance, nCmdShow))
            return FALSE;

    while (GetMessage(&Msg, NULL, 0, 0))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
}

BOOL Register(HINSTANCE hInstance)
{
    WNDCLASS WndClass;
        
    WndClass.style            =    CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc    =    WndProc;
    WndClass.cbClsExtra        =    0;
    WndClass.cbWndExtra        =    0;
    WndClass.hInstance        =    hInstance;
    WndClass.hIcon            =    LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hCursor        =    LoadCursor(NULL, IDC_ARROW);
    WndClass.hbrBackground    =    (HBRUSH)(COLOR_BTNFACE+1);
    WndClass.lpszMenuName    =    NULL;
    WndClass.lpszClassName    =    szAppName;

    return (RegisterClass(&WndClass) != 0);
}

HWND Create(HINSTANCE hInstance, int nCmdShow)
{
    HWND hwnd = CreateWindow(szAppName, szAppName,
                    WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT, CW_USEDEFAULT,
                    CW_USEDEFAULT, CW_USEDEFAULT,
                    NULL, NULL, hInstance, NULL);

    if (hwnd == NULL)
        return FALSE;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    return hwnd;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message,
                         WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
        HANDLE_MSG(hwnd, WM_DESTROY, SimWnd_OnDestroy);        
        default:
            return SimWnd_DefProc(hwnd, Message, wParam, lParam);
    }    
}

void SimWnd_OnDestroy(HWND hwnd)
{
    PostQuitMessage(0);
}

Код 2.0+SimWnd.cpp+------------------------------------------------Конец

Разбор полетов.
Не маленький код . Но не надо бояться – этот код копируется из приложения в приложение и не надо его учить наизусть (хотя, если есть желание…).
Итак, посмотрим. Три шага создания окна:
1) Регистрация. (Register())
2) Создание. (Create())
3) Обработка сообщений. (WndProc())
Когда мы создаем оконное приложение, мы как бы делаем подкласс объекта «окно» благодаря этим трем шагам. Поясню. При создании кнопки (класс “button”) , регистрацию и обработку сообщений выполняет система, а создание – программист. Программист также может создать свой класс кнопки и сделать ей любые свойства такие, как подсветка или градиент. Но об этом когда-нибудь потом.
При регистрации, мы сообщаем системе, в основном, название нового класса и процедуру обработки его сообщений, ну и некоторые элементы внешнего вида и другие параметры.
Создание окна – тут все просто. Вызов функции CreateWindow(). А при создании нового окна, после этой вызываются ShowWindow() и UpdateWindow(). Они призваны соответственно показать и обновить окно.
Самое сложное и обычно наиболее емкое по коды – это обработка сообщений. Есть такая штука – DefWindowProc – стандартная оконная процедура. Все наше окно полностью работает за счет этой процедуры. Только я поступил так, как делают многие программисты:
Код

#define SimWnd_DefProc DefWindowProc

Просто дал ей свое название. Единственное сообщение, которое она не обрабатывает, это WM_DESTROY – сообщение о закрытии окна. Если его не обрабатывать, то окна видно не будет, но процесс так и останется. Не очень удобно.
Сообщения.
Все функционирование в Windows основано на сообщениях. Даже то, что вы передвигаете мышь. Точнее её перерисовка. А как их получает оконная процедура? Все начинается тут:
Код

while (GetMessage(&Msg, NULL, 0, 0))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

А продолжается тут:
Код

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message,
                         WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
        HANDLE_MSG(hwnd, WM_DESTROY, SimWnd_OnDestroy);        
        default:
            return SimWnd_DefProc(hwnd, Message, wParam, lParam);
    }    
}

Функция GetMessage получает сообщение от системы и пересылает его оконной процедуре. Там программист обрабатывает его так, как хочет. Если он этого не делает или ему этого не нужно, то оно обрабатывается стандартной процедурой. Сообщений очень много и приводить их здесь нецелесообразно – займет пару страниц. Скажу только то, что когда я не знал, как называется сообщение, то открывал файл <WinUser.h> искал WM_NULL и смотрел далее сообщения, а по названию определял назначение, далее по справке и, в конце-концов, можно найти.
Рассмотрим параметры в функции WndProc:
1) Дескриптор окна, к которому относится сообщение.
2) Само сообщение.
3) Параметр сообщения.
4) Параметр сообщения.
Зачем два одинаковых параметра? Во-первых, не совсем одинаковые, а во-вторых смотрим: один параметр – 32 бита и второй 32. Очень многое можно указать в 64 битах, да еще 4 с лишним миллиарда возможных сообщений. Перейдем к практическим занятиям.
Делаем кнопки!
Код 2.1+SimWnd.cpp+------------------------------------------------
Код

#include <windows.h>
#include <windowsx.h>

#define SimWnd_DefProc DefWindowProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL Register(HINSTANCE hInstance);
HWND Create(HINSTANCE hInstance, int nCmdShow);

static char szAppName[] = "SimWnd";
static HWND hMainWindow;

void SimWnd_OnDestroy(HWND hwnd);
BOOL SimWnd_OnCreate(HWND hwnd, CREATESTRUCT* pCreateStruct);
void SimWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);

#define BT_FIRSTBUTTON 10001

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpszCmdParam, int nCmdShow)
{
    MSG Msg;

    if (!Register(hInstance))
            return FALSE;    
    if (!Create(hInstance, nCmdShow))
            return FALSE;

    while (GetMessage(&Msg, NULL, 0, 0))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
}

BOOL Register(HINSTANCE hInstance)
{
    WNDCLASS WndClass;
        
    WndClass.style            =    CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc    =    WndProc;
    WndClass.cbClsExtra        =    0;
    WndClass.cbWndExtra        =    0;
    WndClass.hInstance        =    hInstance;
    WndClass.hIcon            =    LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hCursor        =    LoadCursor(NULL, IDC_ARROW);
    WndClass.hbrBackground    =    (HBRUSH)(COLOR_BTNFACE+1);
    WndClass.lpszMenuName    =    NULL;
    WndClass.lpszClassName    =    szAppName;

    return (RegisterClass(&WndClass) != 0);
}

HWND Create(HINSTANCE hInstance, int nCmdShow)
{
    HWND hwnd = CreateWindow(szAppName, szAppName,
                    WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT, CW_USEDEFAULT,
                    CW_USEDEFAULT, CW_USEDEFAULT,
                    NULL, NULL, hInstance, NULL);

    if (hwnd == NULL)
        return FALSE;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    return hwnd;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message,
                         WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
        HANDLE_MSG(hwnd, WM_DESTROY, SimWnd_OnDestroy);
        HANDLE_MSG(hwnd, WM_CREATE, SimWnd_OnCreate);
        HANDLE_MSG(hwnd, WM_COMMAND, SimWnd_OnCommand);
        default:
            return SimWnd_DefProc(hwnd, Message, wParam, lParam);
    }    
}

void SimWnd_OnDestroy(HWND hwnd)
{
    PostQuitMessage(0);
}

BOOL SimWnd_OnCreate(HWND hwnd, CREATESTRUCT* pCreateStruct)
{
    CreateWindow("button", "Кнопка", WS_CHILD|WS_VISIBLE,
        10, 10, 90, 25, hwnd, 
        HMENU(BT_FIRSTBUTTON), 
        pCreateStruct->hInstance, NULL);
    return TRUE;
}

void SimWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
    switch (id)
    {
        case BT_FIRSTBUTTON:
            MessageBox(hwnd, "Ё-моё!", "Работает,", MB_OK|MB_ICONEXCLAMATION);
            break;
    }
}

Код 2.1+SimWnd.cpp+------------------------------------------------Конец
У Вас мог возникнуть вопрос, как узнать сигнатуру функций обработки сообщений. Просто. В файле <WindowsX.h> есть такой шаблон Cls_OnXXXXX. То есть, если нам нужен обработчик сообщения WM_COMMAND, то ищем Cls_OnCommand и смотрим сигнатуру.
Разбор полетов.
В этом коде мы использовали два новых сообщения: WM_CREATE и WM_COMMAND. Первое программист использует для задания «предпусковых» установок и создания динамических элементов управления. В нашем примере был употреблен второй случай – создание кнопки.
WM_COMMAND призвано реагировать на команды программе, в основном, от элементов управления. Например, на нажатие кнопки.
Заметьте, что объем кода 2.1 не многим больше, чем в 2.0. Об этом я и говорил в начале, что основная часть кода копируется из приложения в приложение.
В обработчике OnCreate вызывается функция CreateWindow, вот ее параметры:
1) Символьное название класса.
2) Название элемента или текс в новом элементе.
3) Стиль окна. Их много…
4,5,6,7) Координаты x, y, dx, dy.
8) Дескриптор окна-родителя.
9) Дескриптор меню или идентификатор элемента.
10) Дескриптор модуля.
11) Указатель на значение, которое будет послано в структуре CREATESTRUCT.
В основном, этот обработчик используется для загрузки настроек, ресурсов, подключения динамических библиотек и т. п.
Обработчик OnCommand имеет менее разнообразное назначение (хотя, кто знает, что можно выдумать…). Этот обработчик получает четыре параметра – дескриптор главного окна, идентификатор элемента, дескриптор этого элемента и дополнительная информация. В последнем примере обрабатывается идентификатор кнопки, который задается 9-м параметром функции CreateWindow, в котором указывается целое число, преобразованное с помощью HMENU. А пример достаточно полно показывает «способ употребления» этого обработчика.

В файле тот же текст, но в формате "doc".
Остаюсь без компьютера (еду в инст). Статью писал наскоро, потому прошу модераторов редактировать недостатки, сообщаяя о них на ПМ.



PM MAIL ICQ   Вверх
Fixin
Дата 25.8.2005, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 8
Всего: 18



А файл вот:

Присоединённый файл ( Кол-во скачиваний: 330 )
Присоединённый файл  Lessons.rar 21,99 Kb
PM MAIL ICQ   Вверх
ShadowPhoenix
Дата 15.6.2006, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 15.6.2006
Где: минск

Репутация: нет
Всего: нет



По поводу первой програмки... попробовал откомпилировать в MVS2005  и получил такую козу:
Код

------ Build started: Project: simple, Configuration: Debug Win32 ------
Compiling...
code.cpp
z:\prog\vc\first mfc program\simple\simple\code.cpp(5) : error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char [29]' to 'LPCWSTR'
        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Build log was saved at "file://\\fdoserv\общий доступ\Prog\VC\First MFC program\simple\simple\Debug\BuildLog.htm"
simple - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

 что я тут не понял:
 1. С какого перепугу "MessageBoxW" вместо "MessageBox", в MSDN такой фишки вообще нет... ну это ладно.
 2. поповоду самого "MessageBox"
в MSDN :
Код

Syntax

int MessageBox
(         
           HWND hWnd,
           LPCTSTR lpText,
           LPCTSTR lpCaption,
           UINT uType
);


Parameters

-hWnd
  [in] Handle to the owner window of the message box to be created. If this parameter is NULL, the       message box has no owner window. 
-lpText
  [in] Pointer to a null-terminated string that contains the message to be displayed. 
-lpCaption
  [in] Pointer to a null-terminated string that contains the dialog box title. If this parameter is NULL, the -default title Error is used. 
-uType
  [in] Specifies the contents and behavior of the dialog box. This parameter can be a combination of flags from the following groups of flags.


т.е. по логике вещей должно приводиться??? или я чего не так понимаю.
далее начал химичить пытаясь его запустить хоть как-то... и пришел к такому вот обрезаному виду:
Код
#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
    LPCWSTR s1,s2;
    MessageBox(NULL, NULL, NULL, MB_OK|MB_ICONEXCLAMATION);
    return 0;
}


 smile так собственно сам вопрос как строку  к этому страшному LPСWSTR приводить... перепробовал все известные мне способы smile , из знакомых никто не знает smile
  

Это сообщение отредактировал(а) ShadowPhoenix - 15.6.2006, 17:56
PM MAIL ICQ   Вверх
Earnest
Дата 15.6.2006, 18:32 (ссылка) |  (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Цитата(ShadowPhoenix @  15.6.2006,  18:55 Найти цитируемый пост)
С какого перепугу "MessageBoxW" вместо "MessageBox", в MSDN такой фишки вообще нет... 

Очень многие имена API, которые описаны в MSDN, есть не функции, а макросы. К ним, в частности, относится и MessageBox. На самом деле есть 2 различных ф-и: MessageBoxA и MessageBoxW. Первая используется, если приложение работает с ANSI-строками, второе - с UNICODE. Соответственно, MessageBox - это либо MessageBoxA, либо MessageBoxW.
Теперь о перепуге.
Неизвестно, с какого перепуга, но начиная с VC 2005, проект по умолчанию генерится как UNICODE. А мужики-то не знают... Сколько уже несчастных новичков на эти грабли наступило. Тебе всего лишь надо свои строки заменить их широкими аналогами. Т.е. добавить L перед кавычками (L"XXX").
Есть способ сделать код независимым от типа используемых символов: 
1) заворачивать все строки в макрос _T: _T("XXX") 
2) всегда использовать t-аналоги CRT-функций: не strlen, а _tcslen, и т.д.
3) использовать типы TCHAR, LPTSTR вместо char, LPSTR...

Теперь ты знаешь, что твое приложение настроено на UNICODE
 smile   

Это сообщение отредактировал(а) Earnest - 15.6.2006, 18:36


--------------------
...
PM   Вверх
maxim1000
Дата 15.6.2006, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 2
Всего: 110



ShadowPhoenix, возможно, эта тема будет полезна:
http://forum.vingrad.ru/index.php?showtopi...p;hl=messagebox 


--------------------
qqq
PM WWW   Вверх
0x07L
Дата 15.6.2006, 19:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Конечно, я здесь далеко не самый умный, но попытаюсь тебе помочь.

MessageBox, CreateWindow и еще много функций, которые ты встретишь в MSDN - это макросы вида

#ifdef _UNICODE
#define SomeFunction(...) SomeFunctionW (...)
#else
#define SomeFunction(...) SomeFunctionA (...)
#endif

Открой WinUser.h и найдешь там множество таких конструкций (в т.ч. и для MessageBox).
Суть конструкций в следующем: если где-нибудь в проекте объявлен _UNICODE
(это можно сделать с помощью директивы препроцессора #define или установить в свойствах проекта),
то препроцессор (специальная вещь, обрабатывающая твой исходный код перед тем, как последний попадет в компилятор)
заменяет вызовы функции SomeFunction на вызовы функции SomeFunctionW.
Если _UNICODE не объявлен, подставляется вызов функции SomeFunctionA (A значит ANSI).

Так в сообщении об ошибках появился MessageBoxW. Именно MessageBoxW, а не MessageBoxA, поскольку в 2005ой Студии Юникод по умолчанию включен. Если он тебе не нужен, его можно отключить в свойствах проекта, и никаких ошибок при компиляции примера у тебя не будет (будет, правда, пара предупреждений о том, что ты злонамеренно отключил Юникод).

Зачем нужен этот Юникод? Дело в том, что обычно текстовые символы кодируются значениями от 0 до 255, занимающими 1 байт. Естественно, что 256 символов недостаточно, чтобы закодировать символы всех национальных алфавитов. На наших с тобой компьютерах русские символы кодируются значениями где-то в интервале 128..255. В индийских, для примера, версиях винды такие же коды будут соответствовать совсем другим символам. Таким образом, у разработчика слишком мало возможностей для локализации своего продукта.

Для того чтобы дать разработчику такие возможности, и был придуман Юникод, в котором каждый символ кодируется двумя байтами (на самом деле все несколько сложнее, но в общем дело обстоит именно так). Для того чтобы обеспечить поддержку Юникода, в заголовочных файлах windows.h и tchar.h объявлено несколько полезных типов данных и макросов.

Во-первых, чтобы все строковые литералы, которые имеются в твоей программе, нужно пометить как "юникодовые". Ставишь перед ними букву L.

"Сказала собака баскервилей." -> L"Сказала собака баскервилей."

Есть полезный макрос _TEXT("..."), чтобы подставлять букву L, когда объявлен _UNICODE.

"Сказала собака баскервилей." -> _TEXT("Сказала собака баскервилей.")

Во-вторых, пометить нужно и символьные константы. Делать это проще всего с помощью макроса _T.

'Ю' -> _T('Ю')

В-третьих, вместо char нужно использовать wchar_t, а лучше макрос TCHAR.

char a; -> TCHAR a;

В-четвертых, указатели на char не забудь поменять на указатели на TCHAR, они же LPTSTR.

char * MyString; -> TCHAR * MyString = LPTSTR MyString.

Что такое LPCWSTR и прочие LP...STR, можно узнать в MSDN (ищи Windows Data Types).
Вот в принципе, и все.

Внимание! Макрос TCHAR объявлен в tchar.h. Подключи его #include <tchar.h> 

  

Это сообщение отредактировал(а) 0x07L - 15.6.2006, 21:32
PM MAIL   Вверх
ShadowPhoenix
Дата 16.6.2006, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 15.6.2006
Где: минск

Репутация: нет
Всего: нет



понял, въехал и разобрался... а вообще по науськаванию комнилятора перешел на класс wchar_t ... пока все работает  smile ... А потом просто перешел на ANSI...

Всех благодря за помощь и понимание smile
PM MAIL ICQ   Вверх
ShadowPhoenix
  Дата 16.6.2006, 17:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 15.6.2006
Где: минск

Репутация: нет
Всего: нет



 smile Хм... возник еще один вопрос... уже по HANDLE_MSG, точнее по тому откуда он берет параметры...

ну в данном случае
Код
 HANDLE_MSG(hwnd, WM_DESTROY, SimWnd_OnDestroy);

можно заменить на 
Код
case WM_DESTROY:
        SimWnd_OnDestroy(hwnd);    
        break;

а вот дальше... Совершенно непонятно откуда береться параметр pCreateStruct при вызове
Код
SimWnd_OnCreate(HWND hwnd, CREATESTRUCT* pCreateStruct)

так же хотелось бы получить комментарии к параметрам функции
Код
SimWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)

попробовал изменить
Код
  HANDLE_MSG(hwnd, WM_COMMAND, SimWnd_OnCommand);

на
Код

    case BT_FIRSTBUTTON:
            MessageBox(hwnd, "Ё-моё!", "Работает,", MB_OK|MB_ICONEXCLAMATION);
            break;
...и не работает  smile -  smile тогда что такое id??? непонял 
PS. Вначале думал здесь тему оставить, но тут вопросов по приведённому тексту всетки больше     

Это сообщение отредактировал(а) ShadowPhoenix - 16.6.2006, 17:18
PM MAIL ICQ   Вверх
0x07L
Дата 16.6.2006, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



2_ShadowPhoenix

Пользуйся поиском. В WindowsX.h:

#define HANDLE_MSG(hwnd, message, fn)    \
    case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

Здесь вместо HANDLE_MSG в зависимости от message подставляется другой макрос
(HANDLE_WM_CREATE для WM_CREATE, HANDLE_WM_COMMAND для WM_COMMAND)

В том же WindowsX.h (немного ниже):

#define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L)

LPCREATESTRUCT - это есть то же самое, что CREATESTRUCT *
Вот откуда CREATESTRUCT

В WindowsX.h:

#define HANDLE_WM_COMMAND(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)(lParam), (UINT)HIWORD(wParam)), 0L)

id - это LOWORD(wParam)

Для того чтобы разобраться в этих макросах, посмотри в MSDN описание сообщений WM_CREATE и WM_COMMAND.

PS Кстати, воспользуясь случаем, порекомендую книжку Румянцева "Азбука программирование в Win32 API" (вроде так)
Хорошая книжка для начинающих. 
PM MAIL   Вверх
ShadowPhoenix
Дата 17.6.2006, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 15.6.2006
Где: минск

Репутация: нет
Всего: нет



0x07L, благодарю за книгу...

Если кого заинтересует, то качать можно отсюда...

мне покачто нравиться smile 
PM MAIL ICQ   Вверх
Dmitry_177
Дата 12.10.2006, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Я новичек в Visual C++, решил слезть с Delphi и писать на VC++. Подскажите пожалуйста, как создавать API-приложения VC++? Создаю я новый проект "Win32 Project", потом на сколько я понимаю "stdafx.h" не нужен для написания программ на чистом API, то я его удаляю и в Solution Explorer-е тоже, там еще и "stdafx.cpp".. потом удаляю всю заготовку кода и пишу следующее:

Код

#include <windows.h>
#include <windowsx.h>

#define SimWnd_DefProc DefWindowProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL Register(HINSTANCE hInstance);
HWND Create(HINSTANCE hInstance, int nCmdShow);

static char szAppName[] = "SimWnd";
static HWND hMainWindow;

void SimWnd_OnDestroy(HWND hwnd);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpszCmdParam, int nCmdShow)
{
    MSG Msg;

    if (!Register(hInstance))
            return FALSE;    
    if (!Create(hInstance, nCmdShow))
            return FALSE;

    while (GetMessage(&Msg, NULL, 0, 0))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
}

BOOL Register(HINSTANCE hInstance)
{
    WNDCLASS WndClass;
        
    WndClass.style            =    CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc    =    WndProc;
    WndClass.cbClsExtra        =    0;
    WndClass.cbWndExtra        =    0;
    WndClass.hInstance        =    hInstance;
    WndClass.hIcon            =    LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hCursor        =    LoadCursor(NULL, IDC_ARROW);
    WndClass.hbrBackground    =    (HBRUSH)(COLOR_BTNFACE+1);
    WndClass.lpszMenuName    =    NULL;
    WndClass.lpszClassName    =    szAppName;

    return (RegisterClass(&WndClass) != 0);
}

HWND Create(HINSTANCE hInstance, int nCmdShow)
{
    HWND hwnd = CreateWindow(szAppName, szAppName,
                    WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT, CW_USEDEFAULT,
                    CW_USEDEFAULT, CW_USEDEFAULT,
                    NULL, NULL, hInstance, NULL);

    if (hwnd == NULL)
        return FALSE;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    return hwnd;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message,
                         WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
        HANDLE_MSG(hwnd, WM_DESTROY, SimWnd_OnDestroy);        
        default:
            return SimWnd_DefProc(hwnd, Message, wParam, lParam);
    }    
}

void SimWnd_OnDestroy(HWND hwnd)
{
    PostQuitMessage(0);
}


Возникает такое сообщение "c:\apiwindow\apiwindow.cpp(83) : fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?
 И exe-файл не создается... Что делать? Нужен ли этот stdafx и как с ним обходиться?
PM MAIL   Вверх
maxim1000
Дата 12.10.2006, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 2
Всего: 110



stdafx используется для прекомпилированных заголовков, это не зависит от использования WinAPI (насколько я знаю)
при создании проекта в VC++2005 можно снять галочку "Precompiled headers", в двургих версиях - не помню...


--------------------
qqq
PM WWW   Вверх
Dmitry_177
Дата 12.10.2006, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



У меня тоже VS2005 убрал я "Precompiled headers" только я не увидел там галочки, а выбрал из списка "Not Using Precompiled Headers" в параметре "Create/Use Precompiled Header".. с stdafx теперь проблем вроде как нету, но теперь появились другие ошибки:

1: "c:\api\api\api.cpp(30) : warning C4244: 'return' : conversion from 'WPARAM' to 'int', possible loss of data"  - на строке return "Msg.wParam;" в функции WinMain.

2: "c:\api\api\api.cpp(46) : error C2440: '=' : cannot convert from 'char [7]' to 'LPCWSTR'"  - на строке "WndClass.lpszClassName    =    szAppName;" в функции Register.

3: "c:\api\api\api.cpp(57) : error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'char [7]' to 'LPCWSTR'"  - на строке "HWND hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);" в функции Create.

Подскажите пожалуйста, что опять не так?

Это сообщение отредактировал(а) Dmitry_177 - 12.10.2006, 12:19
PM MAIL   Вверх
maxim1000
Дата 12.10.2006, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 2
Всего: 110



2 и 3 связаны с одним изменением в VC++2005
раньше по умолчанию define UNICODE не добавлялся, так что программа получалась ANSI, ну и функции, соответственно, с окончанием A
в VC++2005 UNICODE по умолчанию включён, так что надо сделать одно из двух:
1. передавать всем API-функциям unicode'овские строки (L"qqq") (ну или использовать TEXT("qqq"), чтобы универсально было)
2. залезть в свойства проекта и Use Unicode set

первое - всего лишь предупреждение
в принципе, конечно, можно внимания на него не обращать
лично я предпочитаю в таких случаях написать явное преобразование (конечно же после того, как проанализирую, корректно ли оно), это приводит к тому, что если ошибка и будет, то её, по крайней мере, будет видно, что ускоряет её поиск...


--------------------
qqq
PM WWW   Вверх
ressac
Дата 2.6.2007, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



я компилю первые два примера под gcc и у меня вместе с окном открывается консоль, как этого избежать?
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.2045 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.