麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > C++ > 正文

詳解Visual C++事件編程

2023-06-06 12:10:46
字體:
來源:轉載
供稿:網友

在微軟 .NET 框架中可以定義托管類事件并用委托和 += 操作符處理這些事件。這種機制似乎很有用,那么在本機 C++ 中有沒有辦法做同樣的事情?

確實如此!Visual C++ .NET 具備所謂統一事件模型(Unified Event Model),它可以像托管類一樣實現本機事件(用 __event 關鍵字),但是由于本機事件存在一些不明顯的技術問題,而微軟的老大不打算解決這些問題,所以他們要我正式奉勸你不要使用它們。那么這是不是就是說 C++ 程序員與事件無緣了呢?當然不是!可以通過別的方法實現。本文我將向你展示如何輕松實現自己漂亮的事件系統。

但是在動手之前,讓我先大體上介紹一下事件和事件編程。它是個重要的主題,當今對事件沒有堅實的理解,你是無法編寫程序的——什么是事件以及什么時候使用事件。

成功的編程完全在于對復雜性的掌控。很久以前,函數被稱為“子程序”(我知道,我這樣說證明我已經老了!)管理復雜性的主要方式之一是自頂向下的編程模式。高層實現類似“宇宙模型”,然后將它劃分為更小的任務如:“銀河系模型”以及“太陽系模型”等等,直到任務被劃分為可以用單個函數實現為止。目前自頂向下的編程模型仍被用于過程化的任務實現當中,但它不適用于發生順序不確定的實時事件響應系統。經典的例子便是 GUI,程序必須響應用戶的某些行為,比如按鍵或是鼠標移動。實際上,事件編程很大程度上源于圖形用戶界面的出現。

在自頂向下的模型中,在頂部的高級部分對低級的實現各種不同任務的函數——如 DoThis,DoThat 進行食物鏈式的調用。但不久以后,低層部分需要回調(talk back),在 Windows 中,可以調用 Rectangle 或 Ellipse 繪制一個矩形或橢圓,但最終 Windows 需要調用你的應用程序來畫窗口。但應用程序都還不存在,它仍然處于被調用度狀態!那么 Windows 如何知道要調用哪個函數呢?這就是事件用處之所在。


Figure 1 自頂向下和自底向上

在每個 Windows 程序的核心——不論是直接用 C 語言編寫的還是使用 MFC 或 .NET 框架類編寫——都是一個處理消息的窗口過程,這些消息如:WM_PAINT, WM_SETFOCUS 和 WM_ACTIVATE。你(MFC 或 .NET)實現窗口過程并將它傳遞給 Windows。到了該畫窗口,改變輸入焦點以及激活窗口的時候,Windows 用相應的消息代碼調用你的過程。這個消息就是事件。窗口過程就是事件處理器。如果過程化編程是自頂向下的,事件編程是自底向上。在典型的軟件系統中,函數的調用流是從較高級部分到低級部分進行的;而事件是以相反的方向過濾的,如Figure 1 所示。當然,在現實的開發中層次關系并不總是這么清晰。許多軟件系統看起來更像 Figure 2 所示的情況:


Figure 2 混合模型

那么到底什么叫事件?其實,事件就是回調。而不是在編譯時就已知名字的函數調用,組件調用在運行時調用你提供的函數。在 Windows 中,它是一個窗口過程。在 .NET 框架中,它叫做委托。不管術語怎么叫,事件提供了一種軟件組件調用函數的方式,這種調用方式直到運行時才知道要調用什么函數。回調被稱為事件處理器。發生或觸發一個事件意味調用這個事件處理器。為此,事件接收部分首先得給事件源提供一個事件處理器的指針,這個過程叫注冊。

通常在以下幾種場合下我們要使用事件:

通知客戶機實際的事件:用戶按下某個按鍵;午夜時鐘敲響;風扇停止工作造成 CPU 燒毀;

當拷貝文件或搜索巨型數據庫時,報告耗時操作的過程,組件可以周期性地觸發某個事件以報告已拷貝了多少文件或已搜索了多少記錄;如果你使用 IWebBrowser2 在自己的應用程序中宿主 IE,報告所發生的重要的或引起注意的事件,瀏覽器會在導航到某個新頁面之前或之后通知你,或者在創建一個新窗口時通知你。

調用應用程序提供的算法:C 運行時庫函數 qsort 排序對象數組,但你必須提供比較函數。借助許多 STL 容器也能實現同樣的訣竅.大多數程序員不會調用 qsort 回調某個事件,但你沒有理由不考慮那種方式。它是“時間比較”事件。

一些讀者問:異常和事件之間有什么差別?主要差別是:異常表示不應該發生的意外情況。例如,你的程序運行耗盡內存,或者遇到被零除。這些都是你并不希望發生的異常情況,并且一旦出現這些情況,你的程序必須要做出相應的處理。另一方面,事件則是每天常規操作的部分并且完全是預期的。用戶移動鼠標或按下某個鍵。瀏覽器導航到一個新頁面。從控制流的角度看,事件是一次函數調用,而異常則是堆棧的突然跳躍,用展開的語義銷毀丟失的對象。

有關事件常見的概念誤解是認為它們是異步的。雖然事件常常被用于處理用戶輸入和其它異步發生的行為 ,但事件本身是以同步方式發生的。觸發一個事件與調用該事件處理器是同一件事情。用偽碼表示就像如下的代碼段:

// raise Foo event
        for (/* each registered object */) {
             obj->FooHandler(/* args */);
        }

控制立即傳到事件處理器,并且不會返回,除非處理完成。某些系統提供某種以異步觸發事件的方式,例如,在 Windows 中,你可以用 PostMessage 代替 SendMessage。控制會從 PostMessage 立即返回,該消息是后來才處理的。但是 .NET 框架中的事件以及我在這里討論的事件是在觸發時被立即處理的。當然,你總是可以觸發來自運行在單獨的線程中的消息代碼事件,或者使用異步委托調用在線程池中執行每個事件處理器,在這種情況下,相對于主線程來說,事件是異步發生的。Windows 處理事件的方式完全是通過窗口過程以及一成不變的 WPARAM/LPARAM 參數,按照現代編程標準來說,簡陋而粗糙。即便是在今天,每個 Windows 程序仍然在使用這種機制。有些程序員為了傳遞事件,甚至創建不可見窗口。窗口過程并不是真正意義上的事件機制,因為在 Winodows 中每個窗口只允許有一個窗口過程,雖然也可以鏈接多個過程,比如每個過程都調用其前面的過程,也就是眾所周知的子類化過程。在真正的事件系統中,相同的事件可以不分等級地注冊多個接收者。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 56av国产精品久久久久久久 | 欧美精品久久久久久久久久 | 性欧美日本 | 国产男女爽爽爽爽爽免费视频 | 久久手机在线视频 | 最污网站| 黄色片一区二区 | 久久精品国产99久久6动漫亮点 | 欧美国产精品久久 | 一级黄色免费电影 | 国产成人高清成人av片在线看 | 欧美大片一级毛片 | 久久国产经典 | 免费高清一级欧美片在线观看 | 久久久大片 | 我爱我色成人网 | 久久伊人精品热在75 | 国产精品午夜性视频 | 激情网站免费观看 | 香蕉视频破解 | 二区三区四区视频 | 国产精品欧美久久久久一区二区 | www.69色| 亚洲视频成人在线 | 国产亚洲在线 | 久久精品之 | 国产免费视频在线 | 久久精品久久精品久久精品 | 久久久久久久久国产 | 91在线色| 久久国产精品免费视频 | chinesexxxx刘婷hd| 视频在线色 | 鲁丝片一区二区三区免费入口 | 一区二区三区在线观看国产 | 伦理三区| 极品销魂一区二区三区 | 中文日产幕无线码6区免费版 | 久草在线手机视频 | 麻豆小视频在线观看 | 亚洲欧美在线视频免费 |