日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

易语言微凉模块oracle,跟着微凉学易语言 【简单子类化】

發布時間:2023/12/2 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 易语言微凉模块oracle,跟着微凉学易语言 【简单子类化】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本帖最后由 【微涼清風】 于 2011-1-20 18:23 編輯

易語言的子類化文章太少了,本人文筆也不好哈,看看VB得吧,別說英文看不懂,看不懂你的易語言水平永遠不會提高!一,初識子類

當你還不碰過子類的時候,你看到這個標題,定會問:"啥叫子類?".因為你知道我定會為你解答.(陰險哪~~~),因為鄙人文才不好,不知如何以最詳細最能理解的方式為你解答,所以到網上偷了一段,還請各位笑納:

子類處理,是一種功能強大的技術,它的作用是對發送到窗口的消息進行處理,我們完全可以用自己定制的一個窗口函數替代它,并保留指向默認窗口函數的指針,當一個消息到達窗口時,自制的窗口函數會攔截它并進行識別處理,對不能識別或不需進行特別處理的消息,就通過指向默認窗口函數的指針傳遞給默認的窗口函數進行處理,這樣便擴充了默認窗口函數的功能。這種用定制的窗口函數代替默認的窗口函數,攔截并處理到達窗口的消息的技術,我們就稱之為“子類處理”,定制的函數我們稱之為“回調函數”。

上面解釋可能較復雜,但是我們現在也沒必要完全搞懂它,因為有了實例這一切就自然明白了.

首先,在使用子類的時候,我們需要用到三個API函數,它們分別是 GetWindowLong, SetWindowLong, CallWindowProc(沒嚇到你吧?),這三個函數不難,可以說是很簡單,有了它們,我們實現子類化成為可能,先來看看 GetWindowLong API函數的原型:

Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long

前面的我都不說了,只看參數:

ByVal hwnd As Long ,不用我說了吧?傳句柄的(問:誰的句柄? 答:當然是你要子類的那個窗口的句柄啦)

ByVal nIndex As Long ,咳咳,這個嘛,需要傳遞一個常量,至于傳遞什么樣的常量,咱們用前段時間學習的API分析大法分析下不就OK了么?(嘿~~聰明)

第二個參數具體傳遞什么樣的參數,根據這個API的名稱進行分析(問:為什么啊? 答:倒,API的常量一般都和API名字有很大關聯的,難道還分析你的名字不成么?),首先是??Get = G, Window = W, Long = L,合成以后就是 GWL_ ,OK ,打開API 瀏覽器,轉到常量,輸入 GWL_ 四個字符看看?有沒?沒有我馬上玩游戲去~~~~~~~~~~

Public Const GWL_EXSTYLE = (-20)

Public Const GWL_HINSTANCE = (-6)

Public Const GWL_HWNDPARENT = (-8)

Public Const GWL_ID = (-12)

Public Const GWL_STYLE = (-16)

Public Const GWL_USERDATA = (-21)

Public Const GWL_WNDPROC = (-4)

很多哈,但是實現子類的時候我們只需要一個,那就是 GWL_WNDPROC,至于其它的常量我建議大家看看MSDN,如果你看不懂的話可以參考下我以前發的關于一篇大量使用 GetWindowLong 和 SetWindowLong 兩個API函數的文章,地址是: http://www.vbgood.com/viewthread.php?tid=46956&highlight= (建議學完該段API介紹再看)

然后,我們再看看 SetWindowLong 原型:

Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

參數:

ByVal hwnd As Long ,句柄,還是句柄

ByVal nIndex As Long ,好奇的你可能已經發現了這個參數和 GetWindowLong 的第二個參數一樣的耶?那么恭喜你,是一樣的,包括傳遞的參數都是一樣的,如果你不服氣你去試下有沒有 SWL_ 開頭的常量.^_^

ByVal dwNewLong As Long ,這個嘛~~, 參數的名稱已經說明這是一個 New(新的)Long(長整形),當然這里的長整形是指一個地址 Address , you know ?

前段時間我們知道了 Get 與 Set 的區別,那就是一個獲取,一個設置,當然這個也不例外.再來看看 CallWindowProc 這個API的原型:

Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

參數:

ByVal lpPrevWndFunc As Long ,這個,我先試著拆分看看意思, Prev 的意思可能是 Previous(原始的), Wnd 自然是 Window(窗口) 意思咯,最后一個 Func 應該是 Function(函數),看看前面的 lp ,如果你會匈牙利命名法的話可以很明顯看出來,該參數應該傳一個指針,當然VB默認不支持指針,所有的指針類型都是以Long代替(注:貌似在32位系統中指針本來就是一個四字節的整形變量).那么這個參數的意思就是需要傳遞一個原始窗口指針,至于為什么,在這會可能說不清楚,咱們接著往下看.

ByVal hWnd As Long , 啥也不說了,句柄唄.

ByVal Msg As Long, 消息撒.至于傳什么,那就接著往下看

ByVal wParam As Long , 還是那句老話,根據 Msg 消息來定,前篇API教程中我們說過 SendMessage 后面二個參數的具體定義,本次這些也一樣

ByVal lParam As Long , 同 wParam 解釋一樣

這個API的用途就是把已處理的消息按 lpPrevWndFunc(原窗口消息地址) 返回給該地址.

好了,這段算是介紹完了,可能你還處于云山霧里,不過別擔心,我能讓你吃虧嗎?哈哈哈~~~~~

二,回調函數

在調用過程時指定的自定義函數被稱為回調函數?;卣{函數(通常簡稱為“回調”)能夠對過程提供的數據執行指定的操作?;卣{函數的參數集必須具有規定的形式,這是由使用回調函數的 API 決定的。關于需要什么參數,如何調用它們,請參閱 API 文檔。

從上面一段文字描述中我們可以看出,回調函數說白了就是一段自定義的過程函數,至于是什么樣的自定義函數,那都是由API來決定的.那么有人會問:咱們這個實現子類化的回調函數是怎么定義的呢?問的好,當然,我還是那句老話,如果你有MSDN的話,建議看看.這里我們實現的子類的回調函數是下面這種樣子:

Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

怎么樣?(網友: 好復雜啊 答:不會吧?這都復雜?那我介紹一個容易記住的方法,把 SendMessage API中的幾個參數拿過來用就行了,是不是發現它們都是一樣的?然后把最后一個參數改成 Byval ???? Long 就行了),可見這個回調函數和 SendMessage 好像啊,幾乎差不多,不過要注意的是: SendMessage 最后一個參數是 lParam As Any,當然 SendMessage 的最后一個參數也可以改成 Byval lParam As Long,當然這里是根據你的需要去定的.

OK,該了解了我們都了解的差不多了?現在該是我們實際操作的時候了,打開VB6,新建標準EXE,然后新建一個標準模塊.

注意哦:用VB進行子類是危險的,你要時刻記得保存你的VB文檔,否則你寫了半天的代碼會因為突然崩潰而沒保存,到那時就別怪我沒提醒你哦.哈哈~~~~~~

提示:在VB中進行子類時,默認只能在標準模塊中進行

三,實際操作的機會來了

在 Form1 中的代碼:

Private Sub Form_Load()

pWndProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)

SetWindowLong Me.hwnd, GWL_WNDPROC, AddressOf WindowProc

End Sub

Private Sub Form_Unload(Cancel As Integer)

SetWindowLong Me.hwnd, GWL_WNDPROC, pWndProc

End Sub

在 Module1 中的代碼:

Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long

Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Public Const GWL_WNDPROC = (-4)

Public pWndProc As Long

Public Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Debug.Print Hex$(Msg)

WindowProc = CallWindowProc(pWndProc, hwnd, Msg, wParam, lParam)

End Function

就這么一點代碼就能實現VB中的子類,可以說是比較簡單的,先來看看 Module1 中的代碼,至于API函數和常量的聲明我就不說了.

首先我們聲明了一個 Public pWndProc As Long 變量,這里主要是把它當然指針來使用,這里我們再看看 Form1 中的代碼:

pWndProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)??,可見窗口初始時先獲取當前窗口的消息地址,然后再使用 SetWindowLong Me.hwnd, GWL_WNDPROC, AddressOf WindowProc 把地址指向模塊中的 WindowProc 回調函數,我們在分析 SetWindowLong, 前面兩個參數我就不說了,后面一個用到了 Addressof 函數,這個函數的功能就是返回一個函數的地址.再看看 SetWindowLong 最后一個參數, dwNewLong 肯定與一個新的參數有關,而這里正是指向我們參數自定義的函數地址.

我們不可能 SetWindowLong Me.hwnd, GWL_WNDPROC, WindowProc 這樣傳遞是吧?這樣直接把函數當做一個參數是不對的,而第三個參數正好是一新地址,所以我們通過 AddressOf WindowProc 該回調函數地址設置成當前窗口的消息地址,這樣我們就能通過 WindowProc 回調函數處理我們的消息了.

接著看 WindowProc 回調函數里的代碼:

Debug.Print Hex$(Msg) 這句意思是以十六進制的方式查看當前的消息情況.當然你可以運行該代碼,然后你將鼠標移動到Form1窗體上,這時在立即窗口就會顯示相應的消息數據.

WindowProc = CallWindowProc(pWndProc, hwnd, Msg, wParam, lParam) 這句的意思是把不需要處理的消息返回給系統,前面我們分析過 CallWindowProc 函數,后面四個參數我就不多說了,它們都是按照回調函數中的參數原樣返回就行了,主要看第一個參數. CallWindowProc 的第一個參數上面分析時說明為一個地址,這個地址必須是原有的.通過 Form_Load 中的代碼我們就可以看出,先是通過 GetWindowLong 獲取Form1窗口的默認消息地址,然后再通過 SetWindowLong 把消息的流通地址轉到我們的回調函數中,然后通過回調函數處理,當不需要時需要再通過 CallWindowProc 返回給窗體默認的消息地址就行了.

再看 Form_Unload 中的代碼,這是一個還原,主要是當我們退出時不在處理窗體默認的消息時應該返回給系統,這里是需要注意的,否則程序可能會出現異常.

說了這么多,可能有些人還不太怎么明白,不過不要緊,以后多多接觸這方面的例子就自然會明白了.好了,我來擬個運行順序,希望大家能夠明白它們的運行機制.

首先,窗體加載時,我們使用

pWndProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)

保存當前窗體的默認消息地址, 然后再通過

SetWindowLong Me.hwnd, GWL_WNDPROC, AddressOf WindowProc

把當前窗體的默認消息地址設置到我們的回調函數地址處,然后我們就可以通過回調消息來控制當前窗體的消息了

WindowProc = CallWindowProc(pWndProc, hwnd, Msg, wParam, lParam)

當消息不用時,我們就要把這個消息返還給系統.該參數只按原路照寫就行了.這里切記,如果少了這個函數,程序接不到相應的消息會死掉的

SetWindowLong Me.hwnd, GWL_WNDPROC, pWndProc

最后不用時咱們就把地址返還給系統.當然有時缺少這一句不會出現什么問題,但是以良好的SDK編程規則來說,最好把這句寫上.

OK,這段似乎較復雜,不過不要緊,先苦后甜嘛,等你熟練使用子類的時候,你的Windows 編程功力就更上一層樓.

休閑時間廣告: 您曾經是否為無法處理窗口的消息而煩惱?您曾經是否看到別人漂亮的自繪菜單而羨慕?您曾經是否因為自己的窗口功能太單一而憂郁?現在好了,趕快學習VB子類吧,有了它,一切都會好起來的.趕快拿起電話定購吧: 電話:110

上面廣告純屬虛構,如有雷同,算我倒霉.其實子類的好處不止這些,當然也有很多很多,下面我會舉一些例子來說明子類的好處.

四,理論,實操一起抓

1,讓你發消息關不掉我

首先新建標準EXE,然后新建一個標準模塊:

在 Form1 中加入以下代碼

Private Sub Form_Load()

pWndProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)

SetWindowLong Me.hwnd, GWL_WNDPROC, AddressOf WindowProc

End Sub

Private Sub Form_Unload(Cancel As Integer)

SetWindowLong Me.hwnd, GWL_WNDPROC, pWndProc

End Sub

然后再在 Module1 中加入以下代碼:

Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long

Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Public Const GWL_WNDPROC = (-4)

Public Const WM_CLOSE = &H10

Public pWndProc As Long

Public Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

If Msg = WM_CLOSE Then '處理 WM_CLOSE 窗口關閉消息

WindowProc = 1

Exit Function

End If

WindowProc = CallWindowProc(pWndProc, hwnd, Msg, wParam, lParam)

End Function

其它代碼我就不說了,主要是看回調函數中的那幾段處理代碼. 首先通過 Msg 參數判斷當前激發的消息,先前說過,Windows 的所以消息都是以 WM_ 開頭的,大家可以找找看.如果是我們要攔截的消息時,那么用下面代碼

WindowProc = 1

Exit Function

兩句搞定, WindowProc = 1 返回為 True,意思是該消息處理完成,然后 Exit Function 自然是退出該函數,這句代碼的意思說白了就是不讓執行下面的 CallWindowProc,如果你給CallWindowProc執行了,消息也就自然返回給程序了,當程序接到WM_CLOSE,自然就會退出了.所以說白了,子類攔截消息就是不讓執行 CallWindowProc.應該很簡單吧??

好了,運行起來試試(別忘了保存)?如果你的VB崩潰了,說明你的代碼有誤,請仔細檢查下.找一個利用 SendMessage 發送WM_CLOSE消息關閉窗口程序試試,發現無法正常關閉你的窗口吧?(注:別拿 Windows 任務管理器試,因為它不單單只是 SendMessage. 如果你實在拿不出什么工具來試,可以自己寫個 SendMessage me.hWnd, WM_CLOSE, 0, 0 試試)

本帖子中包含更多資源

您需要 登錄 才可以下載或查看,沒有帳號?注冊

x

總結

以上是生活随笔為你收集整理的易语言微凉模块oracle,跟着微凉学易语言 【简单子类化】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。