Содержание материала

 

Попробуем написать с Вами программу, которая не будет пользоваться VCL, а будет использовать вызовы функций Windows API.

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

 На самом деле все очень просто...

Для этого нам необходимо:

 

1. Зарегистрировать класс окна для окна главной формы.

Code:

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. Написать подпрограмму обработки оконных сообщений.

Code:

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. Создать главное окно приложения.

Code:

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. Написать тело программы.

Code:

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.

 

Полный текст програмы:

Code:

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,

GetNextWindow и 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 - функциями на этом.

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить