程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 寫小執行程序

寫小執行程序

編輯:Delphi

象C語言一樣,用Delphi也能寫出只有幾十K、十幾K、甚至只有幾K的小程序,本文將以一個能將Win95桌面藏起來的僅有38K的小程序為例教會讀者這一技巧,同時本文還將涉及Win95 TrayIcon的顯示。

本程序能寫得很小的訣竅是:根本沒有用任何的 Form 。也就是說,源程序只有一個 Desktop.dpr 文件,程序完全用標准的 WINAPI 寫成,由於用到的資源很少,所以程序的體積也很小。當然,用這樣的方法編程時不能使用 Delphi的所見即所得的編程方式。}

{首先看看程序頭的寫法:}
    program DeskPop;
    uses Windows, Messages, ShellAPI, sysutils;
    {$R *.RES}

{可以看出本程序比普通的 Delphi 程序用到的 Unit 少的多。下面聲明了全局常量和變量,暫時可以不管他們。}
    const
    AppName = 'DeskTop Hide';
    var
    x: integer;
    tid: TNotifyIconData;
    WndClass: array[0..50] of char;

{現在進入程序的主要部分,首先是定義了一批過程,為了能讓讀者更好地理解,我們先把這些過程跳過去,先說主程序。主程序位於程序的最後,這樣做的好處是可以直接使用程序中定義的過程。主程序十分簡單:}
    begin
    WinMain;
    end.
{看來所有的工作都由 WinMain 完成了。這個 WinMain 使用標准的 WinAPI 函數進行編程,主要步驟是:先聲明一個窗口類,然後創建一個主窗口,最後進入消息循環,直到程序結束。}

procedure WinMain;
var
Wnd: hWnd; {聲明窗口句柄(Handle)變量}
Msg: TMsg; {聲明消息變量}
cls: TWndClass; {窗口類變量}
begin
{ Previous instance running ? If so, exit }
{ 檢查是否程序已經運行,如果已經運行則調用Panic過程退出 }
if FindWindow (AppName, Nil) <> 0 then
Panic (AppName + ' is already running.');

{ Register the window class }
{ 這裡的注冊窗口類程序是例行公事,照抄即可}
FillChar (cls, sizeof (cls), 0); {用這一句將窗口類變量cls清零)
cls.lpfnWndProc := @DummyWindowProc; {取回調函數DummyWindowProc的地址}
cls.hInstance := hInstance; {實例句柄}
cls.lpszClassName := AppName; {窗口類名}
RegisterClass (cls); {注冊窗口類cls}

{ 現在可以創建程序的主窗口了-在本程序中是個虛擬窗口}
{ Now create the dummy window }
Wnd := CreateWindow (AppName, AppName, ws_OverlappedWindow,
cw_UseDefault, cw_UseDefault, cw_UseDefault, cw_UseDefault,
0, 0, hInstance, Nil);
x:= 0; {變量X其實是個開關變量,記錄現在是否已經隱藏了桌面}

{ 如果窗口創建成功,則顯示窗口,並進入消息循環 }
if Wnd <> 0 then
begin
ShowWindow (Wnd, sw_Hide);{本例中窗口是隱藏的}
{ 下面進入消息循環,該循環將不斷運行直到 GetMessage返回0 }
while GetMessage (Msg, 0, 0, 0) do
begin
TranslateMessage (Msg);
DispatchMessage (Msg);
end;
end;
end;

{現在看來,程序的主框架很明了,但是它還不能完成任何任務。過程 Panic將顯示一個對話框後退出程序,它在 Winmain 過程的開始部分被調用,其實 Panic的功能很簡單,之所以要寫成一個函數的原因恐怕一方面是結構化編程的需要,另一方面借此避開了 String 和 PChar 的轉換。}
procedure Panic (szMessage: PChar);
begin
if szMessage <> Nil then
MessageBox (0, szMessage, AppName, mb_ok);
Halt (0);
end;

{下面是回調(Callback)函數 DummyWindowProc,如果說 Winmain 過程是本程序-或者說是本應用或實例的生命,那麼這個回調函數可以說是主窗口的靈魂。每一個標准的或者說是規范的Windows窗口都有一個回調函數,以處理發給該窗口的消息。所謂“回調”的意思是這個函數不是由程序直接調用的,而是由 Windows 系統調用(還記得我們在窗口類中給lpfnWndProc賦過值嗎),這就是事件驅動編程。}
function DummyWindowProc (Wnd: hWnd; Msg, wParam: Word; lParam: LongInt)
:LongInt; stdcall; {注意這裡有一個 stdcall;定義了回調函數}
var
TrayHandle: THandle;
dc: hDC;
i: Integer;
pm: HMenu;
pt: TPoint;
begin
DummyWindowProc := 0;
{下面兩句是找到 Win95 任務欄的句柄}
StrPCopy(@WndClass[0], 'Progman');
TrayHandle := FindWindow(@WndClass[0], nil);
{下面開始處理消息}
case Msg of
{收到窗口創建消息 - 在任務欄上顯示一個圖標}
wm_Create: // Program initialisation - just set up a tray icon
begin
tid.cbSize := sizeof (tid);
tid.Wnd := Wnd;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved