目前分類: BCB 程式開發筆記 (26)

瀏覽方式: 標題列表 簡短摘要
假設你有一個 TreeView 叫做 tvArticle,有個 PopupMenu 叫做 PopupMenu1,你希望用右鍵可以點選 tvArticle 的節點,然後再顯示右鍵選單。
首先你要把 PopupMenu1 的 AutoPupop 屬性設為 false,然後在 tvArticle 的 OnMouseDown 事件加入以下程式碼。

void __fastcall TForm1::tvArticleMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
TPoint p;
GetCursorPos(&p); // 取得游標在螢幕的真實座標
if (Button == mbRight && tvArticle->GetNodeAt(X, Y) != NULL)
{
tvArticle->GetNodeAt(X, Y)->Selected = true;
PopupMenu1->Popup(p.x, p.y); // 顯示右鍵選單
}
}

以上的程式碼會在你選中 TreeNode 時才會出現右鍵選單,若你希望不選中  TreeNode 也能出現選單的話,就改成以下這樣:

void __fastcall TForm1::tvArticleMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
TPoint p;
GetCursorPos(&p); // 取得游標在螢幕的真實座標
if (Button == mbRight)
{
if (
tvArticle->GetNodeAt(X, Y) != NULL)
 tvArticle->GetNodeAt(X, Y)->Selected = true;
PopupMenu1->Popup(p.x, p.y); // 顯示右鍵選單
}
}

Nelson 發表在 PIXNET 痞客邦 迴響(0) 引用(0) 人氣(462)

這一段程式碼是可以取得指定目錄及其子目錄下,所有副檔名為 .url 的檔案 (沒錯,這就是拿來掃瞄 IE 我的最愛),取得的所有檔名會存放在一個名叫 sList 的 StringList 裡頭。



void __fastcall TForm1::LoadFavorite(AnsiString Dir, TStringList *sList) // Dir 就是你要掃瞄的目錄, sList 拿來存放檔名

{

WIN32_FIND_DATA filedata; // Structure for file data

HANDLE filehandle; // Handle for searching

AnsiString szFileName, szDir;

szDir = IncludeTrailingPathDelimiter(Dir); // 確保最後有反斜線



filehandle = FindFirstFile((szDir + "*.*").c_str(), &filedata); // 因為我們要包含子目錄,所以要用 *.*,不然直接用 *.url 就行了

if (filehandle != INVALID_HANDLE_VALUE)

{

do

{

/* 不處理隱藏檔及 . 跟 .. */

if ((filedata.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0 ||

strcmp(filedata.cFileName, ".") == 0 ||

strcmp(filedata.cFileName, "..") == 0)

continue;

/* 若是資料夾 */

if ((filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)

{

szFileName = szDir + AnsiString(filedata.cFileName);// 資料夾完整路徑

Application->ProcessMessages();

LoadFavorite(szFileName); // 遞迴找下一層目錄

}

else if (ExtractFileExt(filedata.cFileName).LowerCase() == ".url")// 若找到的檔案的副檔名是 .url

{

szFileName = szDir + AnsiString(filedata.cFileName);

sList->Add(szFileName); // 將完整路徑加到 sList 裡頭

Application->ProcessMessages();

}

} while (FindNextFile(filehandle, &filedata));

FindClose(filehandle);

}

}


Nelson 發表在 PIXNET 痞客邦 迴響(0) 引用(0) 人氣(662)

我們可以透過 ComponentCount 來掃瞄 Form 底下的所有元件,進而控制這些元件,例如底下這個 sample code 可以把 Form 底下的 Edit 元件一口氣改掉。

for (int i = 0; i < ComponentCount; ++i)

{

if (Components[i]->ClassNameIs("TEdit"))

((TEdit *)Components[i])->Text = "我被改了";

}



那若是要改某個元件底下的子元件呢? 例如要改 GroupBox 裡頭的所有 Label 要怎辦呢? 這時就要用到 ControlCount 了。

for (int i = 0; i < GroupBox1->ControlCount; ++i)

{

if (GroupBox1->Controls[i]->ClassNameIs("TLabel"))

((TLabel *)GroupBox1->Controls[i])->Caption = "我被改了";

}


這樣就可以了~


再補上一招,若是要修改名稱有固定規則的元件又要怎麼做呢? 例如要修改 Edit1~Edit10 的文字內容。這時我們可以叫出 FindComponent() 來幫忙

for (int i = 1; i <= 10; ++i)
{
((TEdit *)FindComponent("Edit" + IntToStr(i)))->Text = "我被改了";
}

類似地,也可以用 FindChildControl() 找到子元件

for (int i = 0; i < 10; ++i)
{
((TEdit *)GroupBox1->FindChildControl("Edit" + IntToStr(i)))->Text = "我被改了";
}


戲法人人會變,巧妙各有不同。透過以上三個例子,應該可以滿足大部分需要大量修改元件屬性的需求了。至於怎麼應用,就看個人的心思啦 :)






Nelson 發表在 PIXNET 痞客邦 迴響(3) 引用(0) 人氣(748)

void __fastcall TForm1::ListBox1MouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
if (Button == mbRight)
{
ListBox1->ItemIndex = ListBox1->ItemAtPos(Point(X,Y), true);
}
}


Nelson 發表在 PIXNET 痞客邦 迴響(0) 引用(0) 人氣(458)

void __fastcall TformMain::CheckInstance(void)
{
Application->Title = Caption;
HANDLE PrevInstHandle;
Mutex = OpenMutex(SYNCHRONIZE, false, Application->Title.c_str());

/* 檢查是否有重複執行 */
if (Mutex != NULL)
{
/*
* 若有重複,把之前的程式帶到前景,
* 再關閉本身
*/
String AppTitle = Application->Title;
Application->ShowMainForm = false;
SetWindowText(Application->Handle, NULL);
PrevInstHandle = FindWindow("TApplication", AppTitle.c_str());
if (IsIconic(PrevInstHandle))
ShowWindow(PrevInstHandle, SW_RESTORE);
else
{
BringWindowToTop(PrevInstHandle);
SetForegroundWindow(PrevInstHandle);
}
Application->Terminate();
}
else
Mutex = CreateMutex(NULL, false, Application->Title.c_str());
}
//---------------------------------------------------------------------------
void __fastcall TformMain::FormClose(TObject *Sender, TCloseAction &Action)
{
ReleaseMutex(Mutex); // 記得在結束程式前,要釋放為了避免重複執行而產生的 Mutex
}


Nelson 發表在 PIXNET 痞客邦 迴響(0) 引用(0) 人氣(578)

有時候你可能會需要讓使用者在 Memo 貼上文字之後自動換行。要達到這樣的效果有幾種方法辦得到。第一種是在 OnMouseUp event 裡頭偵測使用者是否按下了 Ctrl+V。不過這方法並不是很好,所以在這裡我要介紹第二種方法。第二種方法是直接偵測送到 MemoWM_PASTE 訊息。



// 在 Unit1.h

private: // User declarations

TWndMethod OldMemoProc;

void __fastcall NewMemoProc(TMessage &Message);





// 在 Unit1.cpp

void __fastcall TForm1::NewMemoProc(TMessage &Message)

{

OldMemoProc(Message);

if (Message.Msg == WM_PASTE) // 若是貼上

Memo1->Lines->Add(""); // 就自動換行

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)

{

OldMemoProc = Memo1->WindowProc;

Memo1->WindowProc = NewMemoProc;

}




Nelson 發表在 PIXNET 痞客邦 迴響(0) 引用(0) 人氣(698)

【作者】geniustom

【內文】http://delphi.ktop.com.tw/topic.asp?topic_id=59601



一般人看到【取亂數不重複】..很直接的想法就是一直取,每次取完之後再跟之前的比較..

其實這樣的效率極差!取N個不重複的亂數需要做N階乘次比對..

有學過資料結構的應該都知道.在複雜度裡面..N階乘算是【極差】

取亂數可以使用洗牌法..

意思就是說..

1..假設剛買來的牌..有52張..分別照順序排好...

2..你只需要把52張牌全部攤開..隨便選2張交換...

3..交換52次之後..可以做出很平均的亂數處理..

所以..如果要產生A~B不重複的亂數.演算法如下..

var

Nums: array of integer;

i,j,k,temp: integer;

begin

randomize; 灑下亂數種子

setlength(Nums,B-A) //產生B-A張牌

for i := 0 to (B-A)-1 do

Nums[i] := i; //產生一副新牌..都是照順序排好的

for i := 0 to (B-A)-1 do

begin

j := random(B-A+1); //隨便選兩張牌(索引) 取出0~(B-A)的亂數

k := random(B-A+1);

temp := Nums[j]; //交換兩張隨便取的牌

Nums[j] := Nums[k];

Nums[k] := temp;

end;

for i := 0 to (B-A)-1 do

Nums[j]:=Nums[j]+A; //最後..把這邊的排全部變成A~B的值

end;



假如您要取5個..

那只要選Nums[0]~Nums[4]..就是一組很漂亮的亂數..

效率極佳..只需要O(n)次...

而一般人想到那種差勁的演算法..差不多到100..程式就要死當了


Nelson 發表在 PIXNET 痞客邦 迴響(0) 引用(0) 人氣(715)

int MessageBox(const char* Text, const char* Caption, int Flags);

Text : 您要顯示的訊息

Caption : MessageBox 的標題

Flags : 設定要顯示哪些東西



以下是 Flags 的設定值

0 (MB_OK) : OK按鈕

1 (MB_OKCANCEL) : OK, Cancel按鈕

2 (MB_ABORTRETRYIGNORE) : Abort, Retry, Ignore按鈕

3 (MB_YESNOCANCEL) : Yes, No, Cancel按鈕

4 (MB_YESNO) : Yes, No按鈕

5 (MB_RETRYCANCEL) : Retry, Cancel按鈕

16 : 圖示

32 : 圖示

48 : 圖示

64 : 圖示

0 : 將第一按鈕設為預設

256 : 將第二按鈕設為預設

512 : 將第三按鈕設為預設


將數字加起來就可以得到你要的樣式了。





以下是它的回傳值,代表按了什麼按鈕,您可根據回傳值做些相應的動作。

1 (IDOK)

2 (IDCANCEL)

3 (IDABORT)

4 (IDRETRY)

5 (IDIGNORE)

6 (IDYES)

7 (IDNO)



//這是多行訊息。


String s = "這是測試1\n";

s += "這是測試2";

Application->MessageBox(s.c_str(), "Test", 32+3); //最後的Flag可用數字組合.


Nelson 發表在 PIXNET 痞客邦 迴響(1) 引用(0) 人氣(1280)

1 2 3 4