全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2981
推到 Plurk!
推到 Facebook!

請教自定義函數不能返回值的問題

答題得分者是:jow
踏雪冬思
一般會員


發表:6
回覆:2
積分:1
註冊:2007-10-08

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-10-08 22:13:29 IP:220.170.xxx.xxx 訂閱

我寫了一個自定義函數,用來讀取ini文件,可是不知道怎麼返回值。請老師們指教。
Function Tform1.myini(a,b:string):string;
var
myini:Tinifile;
begin
myini:=Tinifile.Create(ExtractFilePath(Application.ExeName) 'config.ini');
Result:=myini.ReadString(a,b,'');
myini.free;
end;
下面的方法不能返回值
procedure TForm1.Image1Click(Sender: TObject);
begin
edit1.text:=myini('link','image1');
ShellExecute(handle, 'open', j ,nil,nil,SW_SHOWNORMAL);
end;
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-10-08 23:59:33 IP:123.193.xxx.xxx 訂閱
函式的分類: 一般函式, 類別內的函式(Method)


[code delphi]
unit fMain;

interface

uses
Forms;

type

{ TForm1 }
TForm1 = class(TForm)
private
//class method,宣告和定義都在class之內.
function FuncOfObjectA: string;
function FuncOfObjectB(Index: Integer): string;
procedure ProcOfObjectA;
procedure ProcOfObjectB(Index: Integer);
procedure ProcOfObjectC(Index: Integer; var ReturnValue: string);
public
end;

//一般 function 及 procedure,宣告和定義都在class之外.
function FuncOfNormalA: string;
function FuncOfNormalB(Index: Integer): string;
procedure ProcOfNormalA;
procedure ProcOfNormalB(Index: Integer);
procedure ProcOfNormalC(Index: Integer; var ReturnValue: string);

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

function TForm1.FuncOfObjectA: string;
begin
Result := 'The FuncOfObjectA';//返回值
end;

function TForm1.FuncOfObjectB(Index: Integer): string;
begin
Result := 'The FuncOfObjectB with Index = ' IntToStr(Index);//返回值
end;

procedure TForm1.ProcOfObjectA;
begin
//只做動作, 無返回值
end;

procedure TForm1.ProcOfObjectB(Index: Integer);
begin
//接受傳入參數Index, 做動作, 無返回值.
end;

procedure TForm1.ProcOfObjectC(Index: Integer; var ReturnValue: string);
begin
//接受傳入參數Index, 做動作, 有返回值 ReturnValue,稱為 call-by-reference,
//ReturnValue內含值的改變也會改變呼叫端的相對變數,因為二者指向同一塊配置的
//記憶體。另外也有一種稱為call-by-address的方式,具有call-by-reference的效果
//不同的是傳入的參數是呼叫端變數指向的位址。
//而上述的傳入參數 Index 則為 call-by-value, 也就是說即使在此改變了Index的
//內含值, 並不會影響函式呼叫端的數值.
end;

//上述函式因為它的宣告(Declaration)和定義(Definition)都在class(TForm)內,所以
//特別稱之為 class 的 Method.



//一般 function 及 procedure,宣告和定義都在class之外.
function FuncOfNormalA: string;
begin
Result := 'The FuncOfNormalA';//返回值
end;

function FuncOfNormalB(Index: Integer): string;
begin
Result := 'The FuncOfObjectB with Index = ' IntToStr(Index);//返回值
end;

procedure ProcOfNormalA;
begin
//只做動作, 無返回值
end;

procedure ProcOfNormalB(Index: Integer);
begin
//接受傳入參數Index, 做動作, 無返回值.
end;

procedure ProcOfNormalC(Index: Integer; var ReturnValue: string);
begin
//同 class method ProcOfObjectC.
end;

end.
[/code]
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-10-09 00:27:26 IP:123.193.xxx.xxx 訂閱
事件和屬性


[code delphi]
unit Unit2;

interface

uses
Forms, Dialogs;

type
//宣告Event型態, 此為一種函式型態, 且必須用於 class 內.(注意以下的 of object)
TChangeA_Event = procedure(Sender: TObject; OldValue, NewValue: Integer) of object;

TForm2 = class(TForm)
procedure FormCreate(Sender: TObject);
private
FPropertyA: Integer; //Member of TForm2, 此為實際配置的記憶體
FPropertyB: string; //Member of TForm2, 此為實際配置的記憶體

FOnChangeA: TChangeA_Event; //FOnChangeA為一種指向型態為TChangeA_Event的函式指標變數
//未被指定時為 nil.(空指標)

procedure SetPropertyA(const Value: Integer); //set function of PropertyA
function GetPropertyB: string; //get function of PropertyB
procedure SetPropertyB(const Value: string); //set function of PropertyB

//Event Handler, 事件處理程序,參數型態為 TChangeA_Event 所宣告的.
//在 FormCreate時, 指定給函式指標 FOnChangeA. 也可以由TForm2以外的
//class 來指定相對應的 Event Handler.
procedure DO_ONCHANGEA(Sender: TObject; OldValue, NewValue: Integer);

public
property PropertyA: Integer read FPropertyA write SetPropertyA;
property PropertyB: string read GetPropertyB write SetPropertyB;
property OnChangeA: TChangeA_Event read FOnChangeA write FOnChangeA;
end;

var
Form2: TForm2;

implementation

{$R *.dfm}

{ TForm2 }

procedure TForm2.SetPropertyA(const Value: Integer);
begin
if Value <> FPropertyA then
begin
//引發FPropertyA被改變的事件
if Assigned(FOnChangeA) then
FOnChangeA(Self, FPropertyA, Value);//Self 代表 TForm2.

FPropertyA := Value;
//因應FPropertyA被改變, 可能引發的一些動作.

end;
end;

function TForm2.GetPropertyB: string;
begin
Result := FPropertyB;
end;

procedure TForm2.SetPropertyB(const Value: string);
begin
if Value <> FPropertyB then
begin
FPropertyB := Value;
//因應FPropertyB被改變, 可能引發的一些動作.
end;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
//指定event handler.
FOnChangeA := DO_ONCHANGEA;
end;

procedure TForm2.DO_ONCHANGEA(Sender: TObject; OldValue, NewValue: Integer);
begin
ShowMessage('PropertyA 正被改變...');
end;

end.

[/code]
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-10-09 00:34:45 IP:123.193.xxx.xxx 訂閱
說明:
===================引 用 踏雪冬思 文 章===================
我寫了一個自定義函數,用來讀取ini文件,可是不知道怎麼返回值。請老師們指教。
Function Tform1.myini(a,b:string):string;
var
myini:Tinifile;
begin
myini := Tinifile.Create(ExtractFilePath(Application.ExeName) 'config.ini');
Result := myini.ReadString(a,b,'');
myini.free;
end;

//myini是你自訂的 method, 所以沒有問題.
下面的方法不能返回值
procedure TForm1.Image1Click(Sender: TObject);
begin
edit1.text:=myini('link','image1');
ShellExecute(handle, 'open', j ,nil,nil,SW_SHOWNORMAL);
end;

//Image1Click, 是你在TForm1中回應Image1被Click的事件,
//也就是一個Event Handler, 其參數定義權在於TImage, 所以
//沒有回傳值, 如果需要keep一個值,可於TForm1宣告一個變數.(class member)
//在TForm1以外也可以(公用變數).

NOTE:
基本上,上述兩篇回應中所描述的,主要是 class(或object)的 PME(屬性, 方法, 事件),
個人看法提供給大家參考, 初學者應該試著去分辨其中的差異,以後看別人的code
會比較上手.^^

編輯記錄
jow 重新編輯於 2007-10-09 00:37:03, 註解 無‧
jow 重新編輯於 2007-10-09 00:52:36, 註解 無‧
踏雪冬思
一般會員


發表:6
回覆:2
積分:1
註冊:2007-10-08

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-10-09 01:07:15 IP:220.170.xxx.xxx 訂閱
感謝老師的回覆,您的意思是說在Image上不能返回值嗎?

由於我是初次學習自定義函數,你所說的我仍然沒有了解透徹。能否請您幫助寫出代碼,并做上注解?
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-10-09 01:39:34 IP:123.193.xxx.xxx 訂閱
你放在Form1上的Image1是根據一種被定義出來的class型態, 叫做 TImage產生出來的物件.

以下我簡單說明 型別與物件的關係:

想像一下, 好比你刻了個印章,在還沒有打印出任何章子的時候,它就只是一個被刻上特定圖騰(比如說TImage)
的印章,我們稱之為它是一種class(型別), 而不是物件.(我指的是那個圖騰)

而用它打印出來一個一個的章子,我們稱之為Instance, 或產生出來的物件.

用印章來做打印的動作,稱為instanciate.

------------------------------------------------------
所以你的Image1是一個已經被產生出來的實際物件,
在它的定義中有用來回應Mouse Click訊息的機制,
它以Event的方式來通知使用者(你), 它被mouse點擊了
一下, 而你的Image1Click(Sender: TObject);就是你用
來回應Image1通知所做的處理.

這種回應Event(事件)的處理程序我們稱之為Event Handler(事件處理程序),
它必須呼應事件所定義的型態,在你的例子中,這個型態為 TNotifyEvent.
是delphi定義好的一種事件型態, help中可以找到它的定義

type
TNotifyEvent = procedure(Sender: TObject) of object;

注意, 它並沒有回傳值.

觀察我所回應的內容, 你應該試著去了解何謂 class 的 PME.
去體會Delphi對於OOP的實作, (封裝, 繼承, 覆載, 多型).
這是我給你的建議, 先去了解基本觀念和型態.




編輯記錄
jow 重新編輯於 2007-10-09 01:40:21, 註解 無‧
mypigbaby
高階會員


發表:11
回覆:168
積分:155
註冊:2006-07-20

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-10-09 08:37:12 IP:203.73.xxx.xxx 訂閱
豬寶寶這樣的寫法是OK的
您所謂的沒傳回值
要不要追蹤您的CODE
myini:=Tinifile.Create(ExtractFilePath(Application.ExeName) 'config.ini'); <--這個物件有沒有被建立?


同時謝謝JOW前輩的回覆
讓豬寶寶又多學到東西了^^
謝謝
[code delphi]
Function Tform1.myini(a,b:string):string;
var
myini:Tinifile;
begin
myini:=Tinifile.Create('c:\config.ini');
Result:=myini.ReadString(a,b,'');
myini.free;
end;

procedure TForm1.Image1Click(Sender: TObject);
begin
edit1.text:=myini('link','image1');
Image1.Picture.LoadFromFile(EDIT1.Text);
end;
[/code]

CONFIG.INI的內容如下
[link]
image1=C:\pig.jpg
踏雪冬思
一般會員


發表:6
回覆:2
積分:1
註冊:2007-10-08

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-10-09 13:42:43 IP:220.170.xxx.xxx 訂閱
老師回答的很詳細,問題解決了,同時也學到了很多知識,再次表示感謝~
系統時間:2024-04-26 21:17:22
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!