1. 程式人生 > >編譯工程時出現異常“[Error] File not found: 'DIALOG.RES'”怎麼解決

編譯工程時出現異常“[Error] File not found: 'DIALOG.RES'”怎麼解決

高階應用篇:
Delphi是個很有效率的開發工具,但是它有一個缺點就是生成的EXE檔案太大.一個程式就算只有一個空視窗體積也有286KB.如果直接用API來寫的話程式體積是小了,但是又太繁瑣,無法立即看到介面效果,根本談不上是視覺化開發.其實並非"魚與熊掌不可兼得",利用資原始檔我們就可以輕鬆達到這個目的.
在開始之前,我們需要一個可以編輯資原始檔的工具.這類工具很多,比如說Resource WorkShop就是非常好的一個.如果一時找不到,利用VC的編輯器來也是可以的.下面我們就以VC的為例示範如何建立一個視窗資原始檔.執行VC,開啟選單File-->New,將出現一個多項選擇頁.我們選擇Files-->ResourceTemplate,在右邊的File填上Demo,Location選擇儲存路徑,然後點選按鈕OK返回VC開發環境.

選擇選單Insert-->Resource,將出現一個資源型別選擇框.我們把滑鼠移到Dialog上面.不用展開,點選右邊的New即可,這時候返回VC開發環境並出現一個只有關閉按鈕和兩個Button的窗體.將滑鼠選定窗體,擊右鍵選擇最後一項Properties,將出現一個設定視窗,將ID改為"MAINFORM"(注意:跟下面新增的其它控制元件的屬性設定方法不同,主視窗的ID必須把雙引號寫上去,而且名稱必須為大寫.否則程式將找不到資源.程式會一執行就退出了.)Caption改為"安裝程式",這時候可以立刻看到視窗的標題變成了"安裝程式",把Styles的Minimize box選上,More Styles的Center勾上使程式執行時的位置居中.當然你也可以設定它的座標.其它保留預設值即可.回到開發環境,在控制元件框裡面分別選擇一個Static Text,一個Edit Box,一個Button和一個Group Box新增到窗體上面.把它們按照自己的愛好排列整齊.然後逐個修改它們的屬性.方法就是按照上面說的選定控制元件後擊右鍵選擇最後一項Properties,在出現的屬性框裡面修改.其中屬性如下:Group Box的Caption屬性清空,Static Text的Caption屬性改為"請選擇安裝目錄:",Edit Box的ID改為10001.第一個Button的ID為10002,Caption屬性為"選擇",第二個Button的ID為10003,Caption屬性為"安裝",第三個Button的ID為10004,Caption屬性為"退出".為了使程式更加完美,我們為它再新增一個選單IDR_MENU1.選擇Insert-->Resource-->Menu,我們這裡只簡單新增一項"檔案-->退出",其中"退出"的ID為10005.然後在主視窗的屬性Menu設定為IDR_MENU1即可.

為了使程式更加美觀,我們再新增一個小圖示,同時這也將是我們程式的圖示.選擇Insert-->Resource-->Icon-->Import,選擇一個圖示檔案.並將它的ID設定為"MAINICON"(注意:必須把雙引號寫上而且字母為大寫),為視窗新增一個Picture控制元件並設定它的屬性Type:Icon,Image下拉選擇剛才的圖示MainIcon即可.
如果你想為程式在滑鼠新增一些資訊也是可以的.選擇Insert-->Resource-->Version即可.
到這裡我們已經完成了一個簡單的"安裝程式"的窗體設計.實際上我們現在就可以在Delphi中呼叫它了.我們先把"勞動成果"儲存起來.選擇File-->Save As,在檔案型別裡選擇"32-bit Resource File(.res)"儲存為"Demo.res",檔案大小大約為2.65KB.

新建一個副檔名為dpr的文字檔案MyDemo.Dpr,鍵入如下程式碼:
Uses Windows,Messages;
{$R Demo.Res}
function MainDialogProc(DlgWin:hWnd;DlgMessage:UINT;DlgWParam:WPARAM;DlgLParam:LPARAM):integer;stdcall;
begin
Result := 0;
case DlgMessage of
WM_Close:
begin
PostQuitMessage(0);
Exit;
end;
end;
end;
begin
DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc);
end.
用Delphi開啟它編譯一次即可產生一個大小為19KB的EXE.是不是很小!實際上,你甚至只用一行程式碼就把它Show出來,不過程式無法關閉而已.
Uses Windows;
{$R Demo.Res}
function MainDialogProc: integer;
begin
Result := 0;
end;
begin
DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc);
end.
上面的程式只不過是一個空視窗而已,現在我們來寫程式碼響應按下相應按鈕響應的事件.完整程式碼如下:
program MyDemo;
uses Windows, Messages, shlobj;
const
ID_Edit = 10001;
ID_Selet = 10002;
ID_Setup = 10003;
ID_Quit = 10004;
ID_Exit = 10005;
{$R Demo.Res}
var
MainWin: HWND;

function My_Gettext: string;
var
Textlength: Integer;
Text: PChar;
s: string;
begin
TextLength := GetWindowTextLength(GetDlgItem(MainWin, ID_Edit));
GetMem(Text, TextLength + 1);
GetWindowText(GetDlgItem(MainWin, ID_Edit), Text, TextLength + 1);
s := text;
FreeMem(Text, TextLength + 1);
Result := s;
end;

function Getmyname: string;
var
i, j: integer;
begin
J := 3;
for i := 1 to length(ParamStr(0)) do
if ParamStr(0) = '' then J := I;
Result := copy(ParamStr(0), J + 1, length(ParamStr(0)) - J);
end;

function SelectDirectory(handle: hwnd; const Caption: string; const Root:WideString;outDirectory:string): Boolean;
var
lpbi: _browseinfo;
buf: array[0..MAX_PATH] of char;
id: ishellfolder;
eaten, att: cardinal;
rt: pitemidlist;
initdir: pwidechar;
begin
result := false;
lpbi.hwndOwner := handle;
lpbi.lpfn := nil;
lpbi.lpszTitle := pchar(caption);
lpbi.ulFlags := BIF_RETURNONLYFSDIRS + BIF_EDITBOX;
SHGetDesktopFolder(id);
initdir := pwchar(root);
id.ParseDisplayName(0, nil, initdir, eaten, rt, att);
lpbi.pidlRoot := rt;
getmem(lpbi.pszDisplayName, MAX_PATH);
try
result := shgetpathfromidlist(shbrowseforfolder(lpbi), buf);
except
freemem(lpbi.pszDisplayName);
end;
if result then
begin
directory := buf;
if length(directory) <> 3 then directory := directory + '';
end;
end;

function MainDialogProc(
DlgWin: hWnd;
DlgMessage: UINT;
DlgWParam: WPARAM;
DlgLParam: LPARAM
)
: integer; stdcall;
var
MyIcon: HICON;
Sdir: string;
begin
Result := 0;
case DlgMessage of
WM_INITDIALOG:
begin
MyIcon := LoadIcon(hInstance, 'MainIcon');
SetClassLONG(DlgWin, GCL_HICON, MyIcon);
MainWin := DlgWin;
end;
WM_Close:
begin
PostQuitMessage(0);
Exit;
end;
WM_COMMAND:
case LOWORD(DlgWParam) of

ID_Selet:
begin
if SelectDirectory(DlgWin, '請選擇安裝目錄', '', Sdir)
then SendMessage(GetDlgItem(DlgWin, ID_Edit), WM_SETTEXT, 0, lParam(pChar(Sdir)));
end;
ID_Setup:
begin
if My_Gettext = '' then
begin
MessageBox(DlgWin, '請先選擇安裝資料夾!', '資訊', MB_ICONINFORMATION + MB_OK);
Exit;
end;
CopyFile(pchar(ParamStr(0)), pchar(My_Gettext + Getmyname), false);
MessageBox(DlgWin, '安裝完畢!', '資訊', MB_ICONINFORMATION + MB_OK);
PostQuitMessage(0);
Exit;
end;
ID_Quit:
begin
PostQuitMessage(0);
EXIT;
end;
ID_Exit:
begin
if MessageBox(DlgWin, '你點選了選單“退出”,你確定退出程式嗎?', '資訊', MB_ICONQUESTION + MB_OKCANCEL) = IDOK then
PostQuitMessage(0);
Exit;
end;
end;
end;
end;
begin
DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc);
end.
其中SelectDirectory函式的作用是返回一個選擇的檔案路徑.然後把自己拷貝到選擇的目錄下,當然很多處理沒有寫,讀者可以自行新增