請問如何讓TMemo不是被focus時,仍能顯示游標?? |
尚未結案
|
YuHeng
一般會員 發表:8 回覆:13 積分:4 註冊:2003-02-26 發送簡訊給我 |
當TMemo不是被Focus時,其游標會消失,
如此就不會知道其所在的位置,
如何當Focus on 其他元件時,在TMemo的游標不會被隱藏... 試了幾個方法,都不理想....
1.在Memo的OnExit內加上
if(!Memo1->SelLength) {
Memo1->SelSelength = 1;
}
把Memo1->HideSelection 設為 false;
如此雖可標示位置,但意思表達不是很清楚,
會讓user會有要對該字元要做處理的聯想... 2.把其他元件的OnClick內都加上
Memo1->SetFocus();
強迫Focus回Memo1.
但此方法對TEdit,就不可使用..
請問有沒方法可達成我的需求.... 感謝大家的熱心先!!
|
ENIX007
高階會員 發表:28 回覆:274 積分:185 註冊:2003-11-27 發送簡訊給我 |
YuHeng您好
小弟之前也遇過和您類似的問題,當時得到的結論是基本上除了HideSelection
屬性外,只有Focus在Memo上才有可能顯示游標
除非製作假象,如mieng兄所述方法
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=41179
另外,如果您能接受使用SetFocus()方法的話,TEdit倒是可以寫在DbClick()
事件中...
給您一些參考 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ |
m8815010
版主 發表:99 回覆:372 積分:289 註冊:2003-11-13 發送簡訊給我 |
YuHeng你好:
其時我覺得你的第一個方法就很不錯了,只是
你可覺得不夠漂亮吧!但是我覺得第二個方法是不行
的,因為這跟本是把focus切回去吧了,與你的題目
原意完全違反。
這邊我有一個大致功能的方式,應該與ENIX007
兄所提mieng兄的作法不同,精神就是玩message、hook
這樣的事而已。
圖例:
圖例說明:上例可以看到當測試區的TMemo元件focus被初換到其它3個元件時,
它的游標還是在的,而下方可以檢測focus是否真正切換。 使用者也可以測試在其它3個元件(Button1、Button2、RichEdit1)
在被setfocus時是否能正常運作,列如切到RichEdit時就要能key
data進去(而Memo1的游標仍然在),這也是YuHeng兄方法二為什麼
不行的理由。
範例程式: ~~~
TForm1 *Form1;
int i=0;
~~~
//--------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ShowMessage("我被按了!");
SendMessage(Memo1->Handle,WM_KILLFOCUS,0,0);
SendMessage(Memo1->Handle,WM_SETFOCUS,0,0);
}
//---------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
i++;
Form1->Caption="我被按了 : "+IntToStr(i)+" 次";
SendMessage(Memo1->Handle,WM_KILLFOCUS,0,0);
SendMessage(Memo1->Handle,WM_SETFOCUS,0,0);
}
//---------------------------------------------------------
void __fastcall TForm1::RichEdit1Enter(TObject *Sender)
{
SendMessage(Memo1->Handle,WM_SETFOCUS,0,0);
}
//---------------------------------------------------------
void __fastcall TForm1::Memo1Click(TObject *Sender)
SendMessage(Memo1->Handle,WM_KILLFOCUS,0,0);
Button1->SetFocus();
Memo1->SetFocus();
}
//---------------------------------------------------------
void __fastcall TForm1::Memo2MouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
AnsiString s ="Button1 --->";
Memo2->Lines->Add(s+(int)Button1->Focused());
s="Memo1 --->";
Memo2->Lines->Add(s+(int)Memo1->Focused());
s="RichEdit1--->";
Memo2->Lines->Add(s+(int)RichEdit1->Focused());
s="Button2 --->";
Memo2->Lines->Add(s+(int)Button2->Focused());
Memo2->Lines->Add("------------------------");
}
//---------------------------------------------------------- *注意事項*
1. 這個例子只是用onclick、onenter等當成setfocus的事件用,正當
應該找setfocus、或losefocus這樣的事件用,如果沒有就要自已攔
WM_SETFOCUS、WM_KILLFOCUS自已做了。
*2. 上述結果就是如果你用tab鍵來切換focus,就可能不能很正常的運作。
3. RichEdit的加入,是一個明顯的測試,證明當focus切到RichEdit時,
我們就能input data在RichEdit內,而Memo1游在仍在。
4. 上述的例子精神講好聽一點就是代替OS送一個message告訴Memo1它已
經被setfocus了,所以它在收到message後會執行對應的function,生
成游標,但是OS本身並沒有被騙,所以真正的focus仍在RichEdit。
*5. 上述OS沒有被騙的結果就是RichEdit在setfocus時是沒有游標的。
*6. 綜合上述,使用者可以改良程式以達自已需求,另外,顯然的,我們
應該可以欺騙OS,做到同時多個游標。這點可以再研究。
|
ENIX007
高階會員 發表:28 回覆:274 積分:185 註冊:2003-11-27 發送簡訊給我 |
|
YuHeng
一般會員 發表:8 回覆:13 積分:4 註冊:2003-02-26 發送簡訊給我 |
引言: YuHeng你好: 其時我覺得你的第一個方法就很不錯了,只是 你可覺得不夠漂亮吧!但是我覺得第二個方法是不行 的,因為這跟本是把focus切回去吧了,與你的題目 原意完全違反。 這邊我有一個大致功能的方式,應該與ENIX007 兄所提mieng兄的作法不同,精神就是玩message、hook 這樣的事而已。 圖例: 圖例說明:上例可以看到當測試區的TMemo元件focus被初換到其它3個元件時, 它的游標還是在的,而下方可以檢測focus是否真正切換。 使用者也可以測試在其它3個元件(Button1、Button2、RichEdit1) 在被setfocus時是否能正常運作,列如切到RichEdit時就要能key data進去(而Memo1的游標仍然在),這也是YuHeng兄方法二為什麼 不行的理由。 範例程式: ~~~ TForm1 *Form1; int i=0; ~~~ //-------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ShowMessage("我被按了!"); SendMessage(Memo1->Handle,WM_KILLFOCUS,0,0); SendMessage(Memo1->Handle,WM_SETFOCUS,0,0); } //--------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { i++; Form1->Caption="我被按了 : "+IntToStr(i)+" 次"; SendMessage(Memo1->Handle,WM_KILLFOCUS,0,0); SendMessage(Memo1->Handle,WM_SETFOCUS,0,0); } //--------------------------------------------------------- void __fastcall TForm1::RichEdit1Enter(TObject *Sender) { SendMessage(Memo1->Handle,WM_SETFOCUS,0,0); } //--------------------------------------------------------- void __fastcall TForm1::Memo1Click(TObject *Sender) SendMessage(Memo1->Handle,WM_KILLFOCUS,0,0); Button1->SetFocus(); Memo1->SetFocus(); } //--------------------------------------------------------- void __fastcall TForm1::Memo2MouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { AnsiString s ="Button1 --->"; Memo2->Lines->Add(s+(int)Button1->Focused()); s="Memo1 --->"; Memo2->Lines->Add(s+(int)Memo1->Focused()); s="RichEdit1--->"; Memo2->Lines->Add(s+(int)RichEdit1->Focused()); s="Button2 --->"; Memo2->Lines->Add(s+(int)Button2->Focused()); Memo2->Lines->Add("------------------------"); } //---------------------------------------------------------- *注意事項* 1. 這個例子只是用onclick、onenter等當成setfocus的事件用,正當 應該找setfocus、或losefocus這樣的事件用,如果沒有就要自已攔 WM_SETFOCUS、WM_KILLFOCUS自已做了。 *2. 上述結果就是如果你用tab鍵來切換focus,就可能不能很正常的運作。 3. RichEdit的加入,是一個明顯的測試,證明當focus切到RichEdit時, 我們就能input data在RichEdit內,而Memo1游在仍在。 4. 上述的例子精神講好聽一點就是代替OS送一個message告訴Memo1它已 經被setfocus了,所以它在收到message後會執行對應的function,生 成游標,但是OS本身並沒有被騙,所以真正的focus仍在RichEdit。 *5. 上述OS沒有被騙的結果就是RichEdit在setfocus時是沒有游標的。 *6. 綜合上述,使用者可以改良程式以達自已需求,另外,顯然的,我們 應該可以欺騙OS,做到同時多個游標。這點可以再研究。真是太感謝m8815010跟ENIX007了..... 因為功力太淺,都沒想過此方法.... 剛剛測了一下,衍生了另一個問題.... 就是此時游標都會在Memo上.. 相對Edit上反而沒有游標.. 這幾天也努力找解答,目前的了解是,因Caret由Windows handle, 所以Caret會顯示在focus的物件上..目前覺得最佳解決的方法 應該是讓Memo有一個獨立的Caret.如此就不會受系統所控制.. 初步的想法是,create一個 memo的caret,然後去攔截message, 當focus的時候,把該caret殺到,如果沒被focus的時候,就產生... 因對這部分完全沒接觸過,所以還在嘗試中..... |
m8815010
版主 發表:99 回覆:372 積分:289 註冊:2003-11-13 發送簡訊給我 |
|
m8815010
版主 發表:99 回覆:372 積分:289 註冊:2003-11-13 發送簡訊給我 |
引言: YuHeng兄你好,你說的沒錯,RichEdit1並沒有游標出來,正如我在*注意事項* 中特別強調的: *5. 上述OS沒有被騙的結果就是RichEdit在setfocus時是沒有游標的。 正因為OS沒有被騙,所以OS它default只容許一個AP有一個游標,故當Memo1 有游標時,RichEdit1是沒有的。下面再稍做細部說明: 首先,YuHeng兄你後來說的方法,下列例子可能可以參考,不知你有沒有試過://----------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { if (!CreateCaret(Memo1->Handle,NULL,0,19)) { ShowMessage("Fail!"); return; } if (!ShowCaret(Memo1->Handle)) ShowMessage("Showing Fail!"); } //----------------------------------------------------------- void __fastcall TForm1::RichEdit1Enter(TObject *Sender) { if (!CreateCaret(Memo1->Handle,NULL,0,19)) { ShowMessage("Fail!"); return; } ShowCaret(Memo1->Handle); Sleep(2000);<----可看出游標確實有設給Memo1,只是又跳回給RichEdit1了! } //------------------------------------------------------------如同你說的,在focus被切為其它子元件時,先做一個游標給Memo1,再讓 它show出,這個在focus切到Button1中是可行的(下圖中focus為Button1, Memo1的游標仍在),但在focus切到RichEdit1時,仍是只有RichEdit1有游標! 圖例: 這是因為當focus切為Button1時,這個Window(Application)依照我們的程式碼 create一個游標給Memo1,而因為Buuton1(focus況態中)並沒有需要用游標,所 以OS並不需要搶回這個游標給Button1(應該是說先把Memo1的destroy,再建一個新的給Button1),而RichEdit1則反之。故仍不行成功! 下面的圖例是Win API的說明,但最重要的是說明OS對游標的Default管理原則! 講了這麼多,遶了一圈,我仍覺得還是老話一句:既然OS只允許一個視窗有一個游標(for default),那麼今天你要讓多個子元件都有游標,那就要騙它,也就是作system hook什麼之類的動作了。 哈哈,那為什麼我沒有做出來呢?因為我也沒實作過(今天還要上班勒!),所以>>< face="Verdana, Arial, Helvetica"> |
YuHeng
一般會員 發表:8 回覆:13 積分:4 註冊:2003-02-26 發送簡訊給我 |
這幾天想了一個方法可以達到我的需求,
我需求主要是要讓user在編輯時,如再使用其他元件時,
可以知道自己在TMemo內所在的位置,
因此開始時會想要有兩個Caret,可是受到系統限制,此功能要達成,
可能非我能力所及,因此又重新思考一下....
如果我不是focus在TMemo時能在caret所在的文字標示'|'或畫個底線,
應該就能達成我的需求....
可是TMemo又沒又Canvas物件,如要加上Canvas物件,工程可能太浩大...
找了版上相關的討論,看到有人推薦TSynEdit,研究了一下,可以達成我的需求...
目前我使用的方法如下: //---------------------------------------------------------------------------
#include
|
YuHeng
一般會員 發表:8 回覆:13 積分:4 註冊:2003-02-26 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |