前兩日,偶見部落格“建立類似於IME視窗的非啟用視窗”,覺得內容不錯,決定試了試,發現有瑕疵,現將自己的測試過程賦予其後(本文測試用的是VB2005),和各位網友交流。
按照那篇的博文的第一種方法,建立了Form1,改寫了Form1的CreateParams屬性,將FormBorderStyle設定為System.Windows.Forms.FormBorderStyle.None。
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim tC As CreateParams = MyBase.CreateParams
tC.ExStyle = tC.ExStyle Or &H8000000
Return tC
End Get
End Property
測試了一下,不錯,和開啟的“記事本”做了比較,當我單擊Form1的時候,游標還在“記事本”裡。
於是,又建立Form2,並改為啟動視窗,上面添加了Textbox1控制項,在該控制項的雙擊事件,啟動Form1
Private Sub TextBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.DoubleClick
Form1.Show()
End Sub
按照設想,雙擊文字框的時候,彈出Form1,游標仍然在文字框內。
不成想,游標不見了,文字框失去焦點,焦點在Form1上(後來將Form1的FormBorderStyle設定為System.Windows.Forms.FormBorderStyle.FixedToolWindow後證實了這一點。焦點的確移到Form1上)
後來想想,在啟動Form1後,強制將焦點切回來後能不能好一點呢,於是,將上面的代碼改為
Private Sub TextBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.DoubleClick
Form1.Show()
Me.Activate()
End Sub
啟動Form1後,游標的確在文字框,但單擊Form1後,游標又沒了,焦點在Form1上。“杯具”呀。
如此努力了若干次,均沒有效果,貌似單個程式裡有兩個Form(或者超過兩個),這個效果就出不來。
後來查了查&H8000000代表的含義是WS_DISABLED,也沒整明白是什麼意思。
後來在網上尋找到一篇文章,通篇的英文,沒有細看,將裡面的代碼測試了一下,能成功。網址如下:
http://www.yortondotnet.com/2006/11/on-screen-keyboards.html
他的代碼中,添加了一段修改Form的WndProc代碼,攔截WM_MOUSEACTIVATE訊息,改為MA_NOACTIVATE。
代碼如下:
Private Const WM_MOUSEACTIVATE As Integer = &H21
Private Const MA_NOACTIVATE As Integer = &H3
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_MOUSEACTIVATE Then
m.Result = MA_NOACTIVATE
Else
MyBase.WndProc(m)
End If
End Sub
經測試,終於達到了效果,啟動Form1,游標在文字框內,無論怎麼點擊Form1,游標都不曾發生變化。
上面這段的代是有效,甚至去掉一開始的改寫CreateParams的代碼,仍然有效。
再做了若干測試,發現上面的代碼效果,如果要成功,還必不可少的是Form上沒有能接受焦點的控制項(Button,TextBox等),而且還不能有標題列。解決的辦法,就是去掉Form的標題列,不使用能接受焦點的控制項(或者是改寫控制項的WndProc過程,攔截接受焦點的訊息,使之不能接受焦點)。雖然Form不能接受焦點,但是經過測試,控制項還是能接受其他的事件(例如:Click,DoubleClick,MouseHover,MouseLeave等事件),合理運用的話,還是能產生不錯的效果。