int apientry winmain что это

int APIENTRY WinMain

3 ответа

Для единообразности и читаемости Microsoft просто переопределила многие фишки (т.е. назначила синонимы)
например, LPSTR это char *, LPSTR обозначает как Long Pointer to STRing (Long Pointer достался еще от реального режима x86 процов, Windows разрабатывается с 1985 года)
DWORD это unsigned int, мы можем писать и то и другое. Но Microsoft предлагает некоторые правила именования
-имена типов заглавными буквами POINT,INT,BOOL
-перед именем переменной префикс, обозначающий её тип или назначение nCount, chBuffer, xDelta, yDelta
-слова в именах ф-ций писать с большой буквы CreateWindow, RegisterClass, CoInitialize
— и т.д.

Так вот
LRESULT CALLBACK WinMain(. )
это
long __stdcall WinMain(. )

разницы, особой нет, НО есть такое НО
Синонимы типов, делаю более гибким перенос с платформы на платформу, достаточно поменять только определение, а всю прогу не надо. Грядёт 64-битная платформа от Intel и AMD, Microsoft ввела еще ряд типов для определённости
DWORD32, DWORD64, INT32, INT64, LONG32. UINT32, UINT64. и DWORD_PTR, INT_PTR. для арифметики с указателями.
там где размер важен (сетевой протокол, структуры в файле) надо использовать эти типы, а то придётся всю прогу перебирать.

О вызове srand(time(0));

1. Ф-ция void srand( unsigned int seed );
устанавливает генератор случайных чисел в некоторое состояние seed, где seek это любое 32-битное число.
2. Ф-ция long time( long *pTimer );
возвращет кол-во секунд прошедших с полуночи, первого января 1970 года (по Гринвичу), также если pTimer не NULL то это же значение записывается в адрес указываемый pTimer.
3. имеем, что srand(time(0)) устанавливает генератор случайных чисел в разное состояние при каждом запуске программы.
4. ф-ция int rand( void ) возвращает псевдослучайное число в диапазоне от 0 до RAND_MAX, и это число зависит от параметра seed в srand(). RAND_MAX в MSVC++ определён как 32767. Если надо сгенерировать число в другом диапазоне [a,b) используйте формулу r = a + rand() % (b-a)

Пример, эта программа будет при каждом запуске выдавать ОДИНАКОВЫЕ a и b
#include
#include

void main()
<
int a = rand() % 10; // п-случ. число от 0 до 9
int b = rand() % 10; // другое число.
printf(«a = %d\nb = %d\n», a, b);
>

#include
#include
#include

int a = rand() % 10; // п-случ. число от 0 до 9
int b = rand() % 10; // другое число.
printf(«a = %d\nb = %d\n», a, b);
>

Источник

Простой способ перейти от main к WinMain, а от командной строки грамотно получить список аргументов

Итак, простой пример, мы хотим старый добрый GLUT (или новый злой FreeGLUT) использовать в своём приложении, но при этом мы любим чтобы приложение под Windows запускалось безо всяких странных консолек на заднем плане. (Согласитесь, пользователей зачастую настораживают всякие досообразные консольки в ваших графических приложениях.) Однако при этом вам жизненно необходим привычный, уютный список аргументов функции main( int argc, char* argv[] ). Причём речь не обязательно про GLUT, вам просто порой жизненно необходимо получить список аргументов в кроссплатформенном приложении.

Итак, начнём с простого, нам потребуется знакомая всем и каждому конструкция, которую мы постепенно будем дополнять:

#ifdef WIN32
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPreInst, LPSTR lpCmdLine, int nCmdShow )
#else
int main( int argc, char *argv[] )
#endif

Если пока никакого отторжения, значит всё хорошо, но я ещё ничего не сделал, не расслабляйтесь. Нам потребуется две WinAPI функции, одна в другой:
CommandLineToArgvW( GetCommandLineW(), &argc ).

Как нетрудно догадаться GetCommandLineW возвращает командную строку вызова приложения в кодировке UTF-16, то есть на каждый символ уйдёт по 2 байта, что есть особенно хорошо для простого русского работяги-программиста порою принимающего аргументы в родной кириллице.

Вроде бы всё хорошо, в самом простом случае нам «всего навсего» понадобится
1) Выделить argc элементов массива char** argv
2) Выделить wcslen( lpArgv[i] ) + 1 байт под каждый элемент argv[i]
3) Преобразовать UTF-16 в лучшем случае в ASCII char, в худшем в ANSI cp1251 — стандартную кириллицу Windows. В первом случае нам потребуется просто wcstombs, во втором придётся использовать WideCharToMultiByte.

int argc;
char** argv;
<
LPWSTR* lpArgv = CommandLineToArgvW( GetCommandLineW(), &argc );
argv = (char**)malloc( argc*sizeof(char*) );
int size, i = 0;
for( ; i

Разумеется по окончании приложения принципиально необходимо за собой почистить.

Введя дополнительное макроопределение MAIN_NEED_CLEAR_ARGV мы облегчаем себе жизнь, варьируя условие проверки для WinMain. Разумеется очистку мы завяжем на этот новый макрос.

#ifdef MAIN_NEED_CLEAR_ARGV
<
int i = 0;
for( ; i

Источник

WinMain: The Application Entry Point

Every Windows program includes an entry-point function that is named either WinMain or wWinMain. Here is the signature for wWinMain.

The four parameters are:

The function returns an int value. The return value is not used by the operating system, but you can use the return value to convey a status code to some other program that you write.

Читайте также:  хронический холецистит вне обострения что это такое

WINAPI is the calling convention. A calling convention defines how a function receives parameters from the caller. For example, it defines the order that parameters appear on the stack. Just make sure to declare your wWinMain function as shown.

The WinMain function is identical to wWinMain, except the command-line arguments are passed as an ANSI string. The Unicode version is preferred. You can use the ANSI WinMain function even if you compile your program as Unicode. To get a Unicode copy of the command-line arguments, call the GetCommandLine function. This function returns all of the arguments in a single string. If you want the arguments as an argv-style array, pass this string to CommandLineToArgvW.

How does the compiler know to invoke wWinMain instead of the standard main function? What actually happens is that the Microsoft C runtime library (CRT) provides an implementation of main that calls either WinMain or wWinMain.

The CRT does some additional work inside main. For example, any static initializers are called before wWinMain. Although you can tell the linker to use a different entry-point function, use the default if you link to the CRT. Otherwise, the CRT initialization code will be skipped, with unpredictable results. (For example, global objects will not be initialized correctly.)

Here is an empty WinMain function.

Now that you have the entry point and understand some of the basic terminology and coding conventions, you are ready to create a complete Window program.

Источник

Int apientry winmain что это

Метод передачи данных между процессами, основанный на использовании файлов, отображенных на виртуальную память, работает достаточно быстро, так как процессы имеют прямой доступ к общим страницам памяти. Тем не менее, при использовании этого метода необходимо заботиться о синхронизации процессов, для чего следует использовать объекты синхронизации.

Если скорость передачи данных не является критичной, можно воспользоваться удобным способом передачи данных, не требующим синхронизации. Этот метод основан на передаче сообщения WM_COPYDATA из одного приложения в другое при помощи функции SendMessage (функцию PostMessage для передачи этого сообщения использовать нельзя).

Ниже мы привели формат структуры COPYDATASTRUCT:

Перед посылкой сообщения WM_COPYDATA приложение должно заполнить структуру COPYDATASTRUCT.

В поле dwData можно записать произвольное 32-разрядное значение, которое будет передано вместе с сообщением.

В поле lpData вы дополнительно можете записать указатель на область данных, полученную, например, при помощи функции HeapAlloc. Размер этой области следует записать в поле cbData.

Когда функция окна принимающего приложения получит сообщение WM_COPYDATA, она должна скопировать в свой локальный буфер данные, которые были переданы вместе с сообщением. И это единственное, что можно с этими данными сделать. Их, например, нельзя изменять. Не следует также надеятся, что данные сохранятся до обработки другого сообщения, поэтому копирование следует выполнить во время обработки сообщения WM_COPYDATA.

Если вам достаточно передать из одного приложения в другое 32-разрядное значение, в поле lpData можно записать константу NULL.

Приложение RCLOCK

Для иллюстрации методов работы с сообщением WM_COPYDATA мы подготовили два приложения, которые называются RCLOCK и STIME.

Приложение RCLOCK раз в секунду получает от приложения STIME сообщение WM_COPYDATA, вместе с которым передается строка текущего времени. Полученая строка отображается в небольшом окне, расположенном в левом нижнем углу рабочего стола (рис. 2.2).

Рис. 2.2. Окно приложения RCLOCK

Рис. 2.3. Исхндное состояние окна приложения RCLOCK

Исходные тексты приложения RCLOCK

Главный файл исходных текстов приложения RCLOCK представлен в листинге 2.3.

Листинг 2.3. Файл rclock/rclock.c

Определения и глобальные переменные

В глобальном массиве szAppName хранится текстовая строка с названием приложения. Это название будет использовано приложением STIME для поиска главного окна приложения RCLOCK.

В глобальных переменных cxChar и cyChar хранятся метрики шрифта с фиксированной шириной символов, которые будут определены на этапе создания главного окна приложения при обработке сообщения WM_CREATE.

Структура rc типа RECT предназначена для хранения размеров окна рабочего стола.

Буфер szBuf используется для хранения данных, передаваемых из приложения STIME при помощи сообщения WM_COPYDATA.

Функция WinMain

Функция WinMain приложения RCLOCK сразу после запуска приложения выполняет поиск своей копии, используя для этого функцию FindWindow. Если такая копия найдена, главное окно этой копии выдвигается на передний план функцией SetForegroundWindow, после чего работа функции WinMain завершается. Такая техника уже использовалась нами ранее.

В том случае, когда запускается первая копия приложения RCLOCK, функция WinMain выполняет обычные действия. Она регистрирует класс окна и создает главное окно приложения. Для того чтобы это окно имело вид, показанный на рис. 2.2, для него указываются стили WS_POPUPWINDOW и WS_THICKFRAME:

Читайте также:  ремень вариатора для бурана какой лучше

Для определения размеров и расположения главного окна приложения RCLOCK функция WinMain определяет размеры окна рабочего стола, сохраняя их в глобальной переменной rc:

Размещение главного окна приложения RCLOCK выполняется функцией MoveWindow, как это показано ниже:

Заметим, что метрики шрифта cxChar и cyChar определяются при обработке сообщения WM_CREATE, который получает управление при вызове функции CreateWindow. Поэтому после возвращения из функции CreateWindow содержимое глобальных переменных cxChar и cyChar будет отражать размеры рабочего стола.

После изменения размеров и расположения главного окна приложения RCLOCK выполняется отображение этого окна и запуск обычного цикла обработки сообщений.

Функция WndProc

В задачу функции WndProc входит обработка сообщений WM_CREATE, WM_DESTROY, WM_PAINT и WM_COPYDATA. Для обработки первых трех сообщений при помощи макрокоманды HANDLE_MSG вызываются функции WndProc_OnCreate, WndProc_OnDestroy и WndProc_OnPaint, соответственно.

Для сообщения WM_COPYDATA в файле windowsx.h, к сожалению, не предусмотрены специальные макрокоманды. Мы могли бы подготовить такую макрокоманду самостоятельно, однако, так как обработка сообщения WM_COPYDATA очень проста, мы использовали классический способ:

Напомним, что вместе с параметром lParam сообщения WM_COPYDATA передается указатель на структуру COPYDATASTRUCT. Приложение, посылающее другому приложению сообщение WM_COPYDATA, подготавливает область данных, записывая ее адрес в поле lpData структуры типа COPYDATASTRUCT. Принимающее приложение должно скопировать эти данные в свой внутренний буфер.

В нашем случае в качестве данных передается строка символов, закрытая двоичным нулем, поэтому для копирования мы используем функцию strcpy.

После выполнения копирования обработчик сообщения WM_COPYDATA вызывает функцию InvalidateRect, что в результате приводит к перерисовке главного окна приложения. В этом окне обработчик сообщения WM_PAINT нарисует текстовую строку, полученную от другого приложения и скопированную только что в буфер szBuf.

Функция WndProc_OnCreate

Функция WndProc_OnCreate вызывается при создании главного окна приложения. Эта функция получает контекст отображения, выбирает в него шрифт с фиксированной шириной букв и определяет его метрики. Ширина и высота символов сохраняются, соответственно, в глобальных переменных cxChar и cyChar. Эти значения используются для вычисления размеров главного окна приложения.

В заверешении функция WndProc_OnCreate записывает в глобальный буфер szBuf строку :

Эта строка будет отображаться в главном окне приложения до тех пор, пока вы не запустите приложение STIME.

Функция WndProc_OnDestroy

Эта функция завершает цикл обработки сообщений, вызывая для этого функцию PostQuitMessage.

Функция WndProc_OnPaint

При обработке сообщения WM_PAINT функция WndProc_OnPaint отображает в главном окне приложения RCLOCK текстовую строку, записанную в буфере szBuf. Для рисования строки используется функция DrawText, так как с ее помощью легко выполнить центровку строки в окне по вертикали и горизонтали.

Файл rclock.h

В файле rclock.h (листинг 2.4) находятся прототипы функций, определенных в приложении RCLOCK.

Листинг 2.4. Файл rclock/rclock.h

Файл resource.h

Файл resource.h (листинг 2.5) создается автоматически и содержит определения для файла описания ресурсов приложения RCLOCK.

Листинг 2.5. Файл rclock/resource.h

Файл rclock.rc

В файле rclock.rc (листинг 2.6) определены ресурсы приложения RCLOCK.

Листинг 2.6. Файл rclock/rclock.rc

Приложение STIME

Приложение STIME работает в паре с приложением RCLOCK, периодически раз в секунду посылая последнему текстовые строки с помощью сообщения WM_COPYDATA. Главное окно приложения STIME не имеет никаких особенностей, поэтому мы его не приводим.

Исходные тексты приложения STIME

Главный файл исходных текстов приложения STIME представлен в листинге 2.7.

Листинг 2.7. Файл rclock/stime/stime.c

Определения и глобальные переменные

Помимо всего прочего в области глобальных переменных определен массив szServerAppName, в котором хранится имя приложения RCLOCK. Это имя будет использовано в функции WinMain для поиска главного окна серверного приложения.

Идентификатор главного окна найденного приложения RCLOCK хранится в глобальной переменной hWndServer. Этот идентификатор используется для посылки сообщения WM_COPYDATA функцией SendMessage.

В области глобальных переменных определена структура cd типа COPYDATASTRUCT, которая совместно с глобальным буфером szBuf используется для передачи текстовой строки в приложение RCLOCK.

Кроме того, определен буфер szTerminated, в котором находится строка символов Terminated. Эта строка передается в приложение RCLOCK перед завершением работы приложения STIME.

Функция WinMain

После поиска своей собственной копии приложение STIME ищет окно серверного приложения RCLOCK:

Если это приложение не найдено, выдается сообщение об ошибке, вслед за чем работа приложения STIME завершается.

В случае успешного поиска идентификатор найденного окна приложения RCLOCK записывается в глобальную переменную hWndServer. Вслед за этим выполняется процедура регистрации класса главного окна приложения STIME, создается главное окно приложения и запускается обычный цикл обработки сообщений.

Функция WndProc

Функция WndProc обрабатывает сообщения WM_CREATE, WM_DESTROY и WM_TIMER, вызывая для этого функции WndProc_OnCreate, WndProc_OnDestroy и WndProc_OnTimer, соответственно.

Функция WndProc_OnCreate

При создании главного окна приложения STIME обработчик сообщения WM_CREATE создает таймер с периодом работы 1 сек, вызывая для этого функцию SetTimer:

Читайте также:  при какой температуре готовится рыба в духовке в фольге

Созданный таймер будет иметь идентификатор CLOCK_TIMER.

Функция WndProc_OnTimer

Функция WndProc_OnTimer получает управление примерно один раз в секунду, обрабатывая сообщения WM_TIMER, поступающие от таймера с идентификатором CLOCK_TIMER.

Прежде всего эта функция формирует строку символов с текущим временем в формате “ЧЧ:ММ:СС”, вызывая библиотечные фукнции системы разработки time и localtime:

Поле dwData не используется.

Заметим, что хотя серверное приложение RCLOCK при копировании полученных данных не использует поле cbData (так как мы передаем строку символов, закрытую двоичным нулем), при подготовке сообщения WM_COPYDATA к отправке необходимо заполнить оба поля: и lpData, и cbData.

Посылка сообщения WM_COPYDATA выполняется очень просто:

Сообщение посылается в окно с идентификатором hWndServer, который был определен в функции WinMain. В качестве параметра wParam вместе с этим сообщением необходимо передать идентификатор окна посылающего приложения, то есть идентификатор окна приложения STIME. Через параметр lParam передается адрес заполненной структуры cd типа COPYDATASTRUCT.

Функция WndProc_OnDestroy

Далее функция WndProc_OnDestroy удаляет таймер и завершает цикл обработки сообщений, вызывая для этого функцию PostQuitMessage.

Файл stime.h

В файле stime.h (листинг 2.8) определен идентификатор таймера CLOCK_TIMER, а также прототипы функций.

Листинг 2.8. Файл rclock/stime/stime.h

Файл resource.h

Файл resource.h (листинг 2.9) создается автоматически и содержит определения для файла описания ресурсов приложения STIME.

Источник

Создание простой обертки над WinAPI для оконных приложений

Некоторое время назад я увлекался созданием оконной библиотеки под Windows на C++. И сегодня я расскажу как написать простую обертку над WinAPI для создания оконных приложений.

Как известно, приложение на голом API состоит из функции WinMain(аналог main для оконных приложений) функции WinProc для обработки сообщений.

Главная сложность при «оборачивании» функций API в классы состоит в том чтобы скрыть WinProc и сделать удобоваримую систему обработки сообщений.

Наша обертка будет состоять из двух классов: CApp и CWnd. Первый — это класс приложения, внутри него нахоится основной цикл сообщений. Второй — это класс окна.

Для начала напишем класс приложения. Он совсем простой:

//Класс нашего приложения
class CApp
<
public :
//Функция запуска нашего приложения
//содержит в себе цикл сообщений
void Run()
<
MSG msg;
while (GetMessage(&msg,0,0,0)!=0)
<
TranslateMessage(&msg);
DispatchMessage(&msg);
>
>
>;

Он содержит единственную функцию Run, внутри которой находится цикл сообещний.
В цикле программа получает сообещения и перенаправляет их в оконную функцию(WinProc).

Далее мы создадим класс CWnd:

//Класс простого окна
class CWnd
<
//Тип указателя на функцию
typedef LRESULT (CWnd::*FuncPointer)(LPARAM,WPARAM);

//Структура указателя на функцию-обработчик
struct POINTER
<
CWnd* wnd; //Указатель на класс, которому принадлежит обработчик
FuncPointer func;
>;

protected :
HWND _hwnd; //Хендл нашего окна
map _msgmap;//Карта сообщений

Он содержит хендл(HWND) окна и карту(map) сообщений.
Также объявляем тип указтеля на функцию-обработчик(FuncPointer) и структуру POINTER. Эта структура содержит указатель на функцию и указатель на объект класса, которому она принадлежит.

Затем добавим функцию создания окна:

if (!_hwnd) return false ;
return true ;
>

В ней мы регистрируем класс окна и создаем само окно с помощью функции CreateWindowEx.
Так же мы передаем в CreateWindowEx указатель на экземпляр CWnd, чтобы в дальнейшем можно было связать APIшный хендл(HWND) и наш экземпляр CWnd.

Теперь передем к главному.
Добавляем оконную функцию в наш класс. Она должна быть статической.

//Оконная функция
//функция в которую поступают сообщения для обработки
static LRESULT CALLBACK _WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
<
CWnd *wnd=0;
//Сообщения WM_NCCREATE приходит до WM_CREATE
//т.е при создании окна
if (message==WM_NCCREATE)
<
//Получаем указатель на экземпляр нашего окна, который мы передали в функцию CreateWindowEx
wnd=(CWnd*)LPCREATESTRUCT(lparam)->lpCreateParams;
//И сохраняем в поле GWL_USERDATA
SetWindowLong(hwnd,GWL_USERDATA,LONG(LPCREATESTRUCT(lparam)->lpCreateParams));
wnd->_hwnd=hwnd;
>
//Теперь получаем указатель на наш экземлпяр окна, но уже из поля GWL_USERDATA
wnd=(CWnd*)GetWindowLong(hwnd,GWL_USERDATA);
if (wnd)
<
//Ищем сообщение в карте
map ::iterator it;
it=wnd->_msgmap.find(message);

//Если сообщение не найдено, то обрабатываем его по умолчанию
if (it==wnd->_msgmap.end()) return DefWindowProc(hwnd,message,wparam,lparam);
else
<
POINTER msg=it->second;
//Вызываем функцию обработчик
LRESULT result=(msg.wnd->*msg.func)(lparam,wparam);
if (result) return result;
>
>
return DefWindowProc(hwnd,message,wparam,lparam);
>
>;

В ней происходит следующее. Сначала мы отлавливаем сообщение WM_NCCREATE. В нем мы получаем переданный в CreateWindowEx указатель и сохраняем его в поле GWL_USERDATA окна. Теперь мы в любой момент можем получить указатель на экземпляр CWnd имея на руках только HWND.
Далее ищем в карте текущее сообщение, и если оно есть вызываем по указателю обработчик из этой карты.

Теперь напишем функцию которая будет добавлять сообщение в карту:

POINTER msg;
msg.wnd=wnd;
msg.func=reinterpret_cast (funcpointer);

Это шаблонная функция и она делает следующее. Преобразовывает указатель на функцию-член любого класса-наследника CWnd, в указатель на функцию-член CWnd. Это нужно для того чтобы привести все указатели к одному типу.

Вот и все, наша обертка готова.
Пример использования:

//Запускаем приложение
CApp *app= new CApp;
app->Run();
return 0;
>

Источник

Сказочный портал