YuHeng
一般會員
![](./myimg/board/mystar_empty.gif)
![](images/icon_photo_none.gif) 發表: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
高階會員
![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif)
![](images/icon_photo_none.gif) 發表:28 回覆:274 積分:185 註冊:2003-11-27
發送簡訊給我
|
------ 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
|
m8815010
版主
![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif)
![](images/icon_photo_none.gif) 發表:99 回覆:372 積分:289 註冊:2003-11-13
發送簡訊給我
|
YuHeng你好:
其時我覺得你的第一個方法就很不錯了,只是
你可覺得不夠漂亮吧!但是我覺得第二個方法是不行
的,因為這跟本是把focus切回去吧了,與你的題目
原意完全違反。
這邊我有一個大致功能的方式,應該與ENIX007
兄所提mieng兄的作法不同,精神就是玩message、hook
這樣的事而已。
圖例:
![](http://delphi.ktop.com.tw/loadfile.php?TOPICID=13667158&CC=305662) 圖例說明:上例可以看到當測試區的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
高階會員
![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif)
![](images/icon_photo_none.gif) 發表:28 回覆:274 積分:185 註冊:2003-11-27
發送簡訊給我
|
哇~~< >
真的可以耶,好厲害< >
當時討論相關問題時,小弟也有研究WM_KILLFOCUS和WM_SETFOCUS這二個
message,但是無論如何做不出這種效果...
太感謝m8815010大大了,這個範例程式碼小弟不客氣收下囉 ![]()
感謝您~~ 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------ 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
|
YuHeng
一般會員
![](./myimg/board/mystar_empty.gif)
![](images/icon_photo_none.gif) 發表: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
版主
![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif)
![](images/icon_photo_none.gif) 發表:99 回覆:372 積分:289 註冊:2003-11-13
發送簡訊給我
|
引言:
哇~~< >
真的可以耶,好厲害< >
當時討論相關問題時,小弟也有研究WM_KILLFOCUS和WM_SETFOCUS這二個
message,但是無論如何做不出這種效果...
太感謝m8815010大大了,這個範例程式碼小弟不客氣收下囉
感謝您~~ 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ 哈哈,>>< face="Verdana, Arial, Helvetica">
|
m8815010
版主
![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif) ![](./myimg/board/mystar.gif)
![](images/icon_photo_none.gif) 發表: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
一般會員
![](./myimg/board/mystar_empty.gif)
![](images/icon_photo_none.gif) 發表:8 回覆:13 積分:4 註冊:2003-02-26
發送簡訊給我
|
這幾天想了一個方法可以達到我的需求,
我需求主要是要讓user在編輯時,如再使用其他元件時,
可以知道自己在TMemo內所在的位置,
因此開始時會想要有兩個Caret,可是受到系統限制,此功能要達成,
可能非我能力所及,因此又重新思考一下....
如果我不是focus在TMemo時能在caret所在的文字標示'|'或畫個底線,
應該就能達成我的需求....
可是TMemo又沒又Canvas物件,如要加上Canvas物件,工程可能太浩大...
找了版上相關的討論,看到有人推薦TSynEdit,研究了一下,可以達成我的需求...
目前我使用的方法如下: //---------------------------------------------------------------------------
#include
#include
#pragma hdrstop #include "mMemoFocus.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CSPIN"
#pragma link "SynEdit"
#pragma resource "*.dfm" struct {
bool Showed;
int X,Y,Len;
} myCaret; void ShowMyCaret(TSynEdit *EDIT);
void HideMyCaret(TSynEdit *EDIT);
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------- void __fastcall TForm1::SynEdit1Exit(TObject *Sender)
{
ShowMyCaret(SynEdit1);
}
//--------------------------------------------------------------------------- void __fastcall TForm1::SynEdit1Enter(TObject *Sender)
{
HideMyCaret(SynEdit1);
}
//--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender)
{
myCaret.Showed = false;
}
//--------------------------------------------------------------------------- void ShowMyCaret(TSynEdit *EDIT)
{
if(myCaret.Showed) {
HideMyCaret(EDIT);
}
myCaret.Showed = true;
myCaret.X = EDIT->CaretXPix();
myCaret.Y = EDIT->CaretYPix() + EDIT->Canvas->TextHeight("H") + 2;
myCaret.Len = EDIT->CharWidth; // save canvas pen info
TPenMode tmpPenMode = EDIT->Canvas->Pen->Mode;
TPenStyle tmpPenStyle = EDIT->Canvas->Pen->Style;
int tmpWidth = EDIT->Canvas->Pen->Width; // set canvas pen
EDIT->Canvas->Pen->Mode = pmNot;
EDIT->Canvas->Pen->Style = psSolid;
EDIT->Canvas->Pen->Width = 2;
// draw my caret
EDIT->Canvas->MoveTo(myCaret.X,myCaret.Y);
EDIT->Canvas->LineTo(myCaret.X+myCaret.Len,myCaret.Y); // restore canvas pen info
EDIT->Canvas->Pen->Mode = tmpPenMode;
EDIT->Canvas->Pen->Style = tmpPenStyle;
EDIT->Canvas->Pen->Width = tmpWidth;
} void HideMyCaret(TSynEdit *EDIT)
{
if(myCaret.Showed) {
myCaret.Showed = false;
// save canvas pen info
TPenMode tmpPenMode = EDIT->Canvas->Pen->Mode;
TPenStyle tmpPenStyle = EDIT->Canvas->Pen->Style;
int tmpWidth = EDIT->Canvas->Pen->Width; // set canvas pen
EDIT->Canvas->Pen->Mode = pmNot;
EDIT->Canvas->Pen->Style = psSolid;
EDIT->Canvas->Pen->Width = 2;
// draw my caret
EDIT->Canvas->MoveTo(myCaret.X,myCaret.Y);
EDIT->Canvas->LineTo(myCaret.X+myCaret.Len,myCaret.Y); // restore canvas pen info
EDIT->Canvas->Pen->Mode = tmpPenMode;
EDIT->Canvas->Pen->Style = tmpPenStyle;
EDIT->Canvas->Pen->Width = tmpWidth;
}
} 執行結果
|
YuHeng
一般會員
![](./myimg/board/mystar_empty.gif)
![](images/icon_photo_none.gif) 發表:8 回覆:13 積分:4 註冊:2003-02-26
發送簡訊給我
|
感謝ENIX007 & m8815010在這個問題給予相當多的協助....
因m兄給了較多的思考方向,因此將此問題給分給了m兄...
|