Написание программ на чистом WinAPI

.
Попробуем написать с Вами программу, которая не будет пользоваться VCL, а будет использовать вызовы функций Windows API.
Приложения такого типа нужны, когда размер исполняемого файла является критичным. Например, в инсталяторах, деинсталяторах, самораспаковывающихся архивах и т.п. В крайнем случае, для того чтобы посмотреть какую работу выполняет за нас VCL, и что из себя представляет Windows-программа.
На самом деле все очень просто...
Для этого нам необходимо:
1. Зарегистрировать класс окна для окна главной формы.

function InitApplication: Boolean;

var

 wcx: TWndClass;

begin

//Заполняем структуру TWndClass

  // перерисовываем, если размер изменяется

  wcx.style := CS_HREDRAW or CS_VREDRAW;

  // адрес оконной процедуры

  wcx.lpfnWndProc := @MainWndProc;

  wcx.cbClsExtra := 0;

  wcx.cbWndExtra := 0;

  // handle to instance

  wcx.hInstance := hInstance;

  // загружаем стандандартную иконку

  wcx.hIcon := LoadIcon(0, IDI_APPLICATION);

  // загружаем стандартный курсор

  wcx.hCursor := LoadCursor(0, IDC_ARROW);

  // делаем светло-cерый фон

  wcx.hbrBackground := COLOR_WINDOW;

  // пока нет главного меню

  wcx.lpszMenuName := nil;

  // имя класса окна

  wcx.lpszClassName := PChar(WinName);

  // Регистрируем наш класс окна.

  Result := RegisterClass(wcx) <> 0;

end;

2. Написать подпрограмму обработки оконных сообщений.

function MainWndProc(Window: HWnd; AMessage, WParam,

  LParam: Longint): Longint; stdcall; export;

begin

 //подпрограмма обработки сообщений

 case AMessage of

  WM_DESTROY: begin

  PostQuitMessage(0);

  Exit;

  end;

  else

  Result := DefWindowProc(Window, AMessage, WParam, LParam);

 end;

end;

3. Создать главное окно приложения.

function InitInstance: HWND;

begin

 // Создаем главное окно.

 Result := CreateWindow(

  // имя класса окна

  PChar(WinName),

  // заголовок

  'Small program',

  // стандартный стиль окна

  WS_OVERLAPPEDWINDOW,

  // стандартные горизонтальное, вертикальное положение, ширина и высота

  Integer(CW_USEDEFAULT),

  Integer(CW_USEDEFAULT),

  Integer(CW_USEDEFAULT),

  Integer(CW_USEDEFAULT),

  0,//нет родительского окна

  0,//нет меню

  hInstance, // handle to application instance

  nil); // no window-creation data

end;

4. Написать тело программы.

var

 hwndMain: HWND;

 AMessage: msg;

begin

  if (not InitApplication) then

  begin

  MessageBox(0, 'Ошибка регистрации окна', nil, mb_Ok);

  Exit;

  end;

  hwndMain := InitInstance;

  if (hwndMain = 0) then

  begin

  MessageBox(0, 'Ошибка создания окна', nil, mb_Ok);

  Exit;

  end

  else

  begin

  // Показываем окно и посылаем сообщение WM_PAINT оконной процедуре

  ShowWindow(hwndMain, CmdShow);

  UpdateWindow(hwndMain);

  end;

  while (GetMessage(AMessage, 0, 0, 0)) do

  begin

  //Запускаем цикл обработки сообщений

  TranslateMessage(AMessage);

  DispatchMessage(AMessage);

  end;

  Halt(AMessage.wParam);

end.

5. Запустить программу на исполнение.;)
Наша программа пока только может немногое - отображать форму, и закрываться после нажатия на кнопку закрытия формы... Но посмотрите на размер исполняемого файла - он больше чем на порядок меньше созданного с использованием VCL.
Полный текст програмы:

program SmallPrg;

uses Windows, Messages;

const

 WinName = 'MainWClass';

function MainWndProc(Window: HWnd; AMessage, WParam,

  LParam: Longint): Longint; stdcall; export;

begin

 //подпрограмма обработки сообщений

 case AMessage of

  WM_DESTROY: begin

  PostQuitMessage(0);

  Exit;

  end;

  else

  Result := DefWindowProc(Window, AMessage, WParam, LParam);

 end;

end;

function InitApplication: Boolean;

var

 wcx: TWndClass;

begin

//Заполняем структуру TWndClass

  // перерисовываем, если размер изменяется

  wcx.style := CS_HREDRAW or CS_VREDRAW;

  // адрес оконной процедуры

  wcx.lpfnWndProc := @MainWndProc;

  wcx.cbClsExtra := 0;

  wcx.cbWndExtra := 0;

  // handle to instance

  wcx.hInstance := hInstance;

  // загружаем стандандартную иконку

  wcx.hIcon := LoadIcon(0, IDI_APPLICATION);

  // загружаем стандартный курсор

  wcx.hCursor := LoadCursor(0, IDC_ARROW);

  // делаем светло-cерый фон

  wcx.hbrBackground := COLOR_WINDOW;

  // пока нет главного меню

  wcx.lpszMenuName := nil;

  // имя класса окна

  wcx.lpszClassName := PChar(WinName);

  // Регистрируем наш класс окна.

  Result := RegisterClass(wcx) <> 0;

end;

function InitInstance: HWND;

begin

 // Создаем главное окно.

 Result := CreateWindow(

  // имя класса окна

  PChar(WinName),

  // заголовок

  'Small program',

  // стандартный стиль окна

  WS_OVERLAPPEDWINDOW,

  // стандартные горизонтальное, вертикальное положение, ширина и высота

  Integer(CW_USEDEFAULT),

  Integer(CW_USEDEFAULT),

  Integer(CW_USEDEFAULT),

  Integer(CW_USEDEFAULT),

  0,//нет родительского окна

  0,//нет меню

  hInstance, // handle to application instance

  nil); // no window-creation data

end;

var

 hwndMain: HWND;

 AMessage: msg;

begin

  if (not InitApplication) then

  begin

  MessageBox(0, 'Ошибка регистрации окна', nil, mb_Ok);

  Exit;

  end;

  hwndMain := InitInstance;

  if (hwndMain = 0) then

  begin

  MessageBox(0, 'Ошибка создания окна', nil, mb_Ok);

  Exit;

  end

  else

  begin

  // Показываем окно и посылаем сообщение WM_PAINT оконной процедуре

  ShowWindow(hwndMain, CmdShow);

  UpdateWindow(hwndMain);

  end;

  while (GetMessage(AMessage, 0, 0, 0)) do

  begin

  //Запускаем цикл обработки сообщений

  TranslateMessage(AMessage);

  DispatchMessage(AMessage);

  end;

  Halt(AMessage.wParam);

end.

Последний раз мы рассмотрели пару ф-й и их особенности(FindWindow,
GetWindow и GetWindowText), однако несмотря на это были вопросы
именно на эту тему - вывод : торопитесь ребята. Старайтесь по
максимуму использовать, то что у Вас уже есть.
Итак вдогонку к 12-у выпуску хочется отметить, что при поиске окон,
как отмечалось, нужен класс и имя, так вот - если Вы ищите DOS-окно,
то его класс всегда = 'tty'.
Сегодня рассмотрим некоторые вспомогательные функции, которые немного
облегчают и нашу жизнь, и программу в целом.
Получить каталог Windows( вдруг при установке Вы назвали его Unix :) ).
var
s1 : array[0..254] of Char;
...
GetWindowsDirectory(s1,255);
В s1 получим искомый путь.
Один момент - не надо описывать s1 просто как PChar, иначе
при выполнении получите неприятное сообщение.
Анологично можно найти и системный каталог. Это тоже важно, поскольку,
например для Win9x это 'Windows\System', а для NT 'System32'.
GetSystemDirectory(s1,255);
255 - это длинна строки. Отдельно подчеркну, что очень рекомендую вместо
этого числа ставить переменную Max_Path, содержащую в себе максимальную
длинну пути в Вашей операционной системе.

Еще очень интересная функция. Она позволяет запретить или разрешить все
действия с окном пользователю.
EnableWindow(H:Hwnd,t:Boolean);
Где h-дескриптор окна, если сказать Application.Handle, то свое окно.
t=False - запретить действия, True - разрешить.
Ну и все с Api - функциями на этом.

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...