1. 程式人生 > >如何使用MFC編寫自定義UI介面【附高仿QQ 2014登陸介面範例程式】

如何使用MFC編寫自定義UI介面【附高仿QQ 2014登陸介面範例程式】

地址: http://blog.csdn.net/hujkay
作者:Jekkay Hu([email protected])
關鍵詞:MFC, 編寫異行窗體,自定義UI控制元件,VC++,異形控制元件,高仿QQ登陸介面, 擷取QQ密碼,QQ釣魚
時間: 2014/4/12

1. 概述

    在開發客戶端程式的時候,稍微有點正常審美觀的人都會對微軟的預設UI介面表示深惡痛絕,連最簡單的預設程式ICON都用那麼低的畫素的ICON,質量差的令人髮指啊。所以,但凡好一點的軟體,都會去找一些介面庫,或者乾脆自己寫個介面庫來美化一下使用者互動介面,免得使用者吐血暴斃。
    網路上有許多介面庫,其中不少是免費的,這裡推薦一款我經常用的介面庫:Skinsharp。這個介面庫,動態編譯版本是免費的,靜態編譯版本是收費的,當然網上肯定有不少破解版本,但是為了中國軟體的前途,大家還是稍微掏點錢買正版吧,有點扯遠了,拽回來!使用第三方提供的介面庫固然能美化程式介面,但有的程式需要一些比較特殊的異形介面,那麼這些介面庫就很難滿足需求了,這樣我們就必須自己去編寫UI外掛了。


2. 編寫自定義UI介面

     編寫自定義UI外掛,涉及到三方面:形狀,介面繪製和事件響應。下面分別對著三個方面進行詳細闡述一下。

    2.1 形狀

        我們先隨便找個軟體,比如金山毒霸吧,如下:
      
      介面是不是很酷,相比Windows自身的介面是不是感覺是天上天下之別。而我們看到這些好看的介面形狀都不是方方正正,全是不規則的形狀,所以我們第一步要做的就是設定視窗的形狀。微軟提供了一個API函式,可以設定窗體的形狀:
int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw);
 其中HRGN是一個用於表示形狀的物件,我們可以用另外一個封裝好的類CRGN來進行操作。該CRGN提供了許多非常友好的介面函式,比如新增一塊區域,減少一塊區域等,具體的可以檢視一下官網的MSDN,下面列舉一些常用的操作。    
    a. 建立一個矩形的區域
          CRgn	rgn;
          rgn.CreateRectRgn(0, 0, nWidth,nHeight);
    b. 在當前的區域中新增一塊的區域
        rcXor.SetRect(0, 0, 1, 2);
        rgn_xor.CreateRectRgn(0, y, border_offset[y], y + 1);
        rgn.CombineRgn(&rgn, &rgn_xor, RGN_OR);
    c. 在當前的區域中只取共同區域
        rcXor.SetRect(0, 0, 1, 2);
        rgn_xor.CreateRectRgn(0, y, border_offset[y], y + 1);
        rgn.CombineRgn(&rgn, &rgn_xor, RGN_AND);
    d. 在當前的區域中異或一塊的區域
        rcXor.SetRect(0, 0, 1, 2);
        rgn_xor.CreateRectRgn(0, y, border_offset[y], y + 1);
        rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR);
      
   區域建立了好了之後,就設定一下窗體的區域:      
SetWindowRgn((HRGN)rgn, TRUE);

下面一段完整的程式碼,供大家參考一下:  

  CDC* pDC = GetDC();


 CRect	rc;
 GetWindowRect(rc);
 rc.OffsetRect(-rc.left, -rc.top);


 CRgn	rgn;
 rgn.CreateRectRgn(0, 0, rc.Width(), rc.Height());
 CRgn	rgn_xor;
 CRect	rcXor;
 
 for (int y = 0; y < nSize; ++y)
 {
  rcXor.SetRect(0, y, border_offset[y], y + 1);
  rgn_xor.CreateRectRgn(0, y, border_offset[y], y + 1);
  rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR);
  rgn_xor.DeleteObject();
 }


 for (int y = 0; y < nSize; ++y)
 {
  rcXor.SetRect(rc.right - border_offset[y], y, rc.right, y + 1);
  rgn_xor.CreateRectRgn(rc.right - border_offset[y], y, rc.right, y + 1);
  rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR);
  rgn_xor.DeleteObject();
 }


 for (int y = 0; y < nSize; ++y)
 {
  rcXor.SetRect(0, rc.bottom - y - 1, border_offset[y], rc.bottom - y);
  rgn_xor.CreateRectRgn(0, rc.bottom - y - 1, border_offset[y], rc.bottom - y);
  rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR);
  rgn_xor.DeleteObject();
 }


 for (int y = 0; y < nSize; ++y)
 {
  rcXor.SetRect(rc.right - border_offset[y], rc.bottom - y - 1, rc.right, rc.bottom - y);
  rgn_xor.CreateRectRgn(rc.right - border_offset[y], rc.bottom - y - 1, rc.right,rc.bottom - y);
  rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR);
  rgn_xor.DeleteObject();
 }


 SetWindowRgn((HRGN)rgn, TRUE);
 m_Rgn.DeleteObject();
 m_Rgn.Attach(rgn.Detach());
 ReleaseDC(pDC);

   2.2 介面繪製

        介面繪製是繁瑣的工作,推薦使用Gdiplus庫來支援一下,在stdafx.h加入如下的程式碼,將其包含進來即可:
#include <gdiplus.h> 
using namespace Gdiplus; 

#pragma comment(lib, "gdiplus.lib")
    自定義繪製介面需要過載一下主要下面的幾個函式:
繪製客戶區域的函式:ON_WM_PAINT()
繪製非客戶區域的函式:ON_WM_NCPAINT()
背景擦除函式:ON_WM_ERASEBKGND()
限定窗體大小的函式:ON_WM_GETMINMAXINFO()
   一般來說,自繪窗體控制元件最主要的就是ON_WM_PAINT()方法,大部分時間都耗在就是在裡面,這個活比較細緻,畫素一個一個地調,沒有耐心的人估計會砸電腦。
    在這裡有技巧需要提一下,如果繪製的介面外掛老一閃一閃的,可以先在記憶體裡面建立一塊畫板,在裡面畫好了之後然後在顯示到介面上,可參考如下的程式碼:
     
   CRect	rcClient;
   GetClientRect(&rcClient);


  CPaintDC	dc(this);
  CDC MemDC;
  MemDC.CreateCompatibleDC(&dc);
  CBitmap memBmp;
  memBmp.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
  CBitmap *pOldmap = MemDC.SelectObject(&memBmp);

  DrawImageStyle(MemDC, rcClient);

  dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &MemDC, 0, 0, SRCCOPY);

  MemDC.SelectObject(pOldmap);
  MemDC.DeleteDC();

  2.3 事件

     事件是指根據使用者的互動動作而觸發某些動作,主要是滑鼠和鍵盤兩種。我這裡主要介紹下滑鼠事件,滑鼠事件可分為:移動,按下,彈起,移入,移出,單擊,雙擊和滾動。在建立自定義建立視窗的時候,千萬不要過載單擊和雙擊的事件,這是非常不好的習慣,而且容易引發各種問題,最好的辦法是自己在按下按鈕的時候模擬單擊或者雙擊的資訊,所以一般來說,過載下面幾個方法即可:
 ON_WM_MOUSEMOVE()
 ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
 ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
 ON_WM_LBUTTONDOWN()
 ON_WM_LBUTTONUP()
 ON_WM_LBUTTONDBLCLK()
     事件和窗體繪製有著緊密的關係,比如一個按鈕,使用者滑鼠移入時是一種狀態,按下時又是一種狀態,彈起式又是一狀態。因此,在繪製窗體時,要根據當前的用於的互動狀態繪製不同的形態,非常考驗一個人的變成能力。

3. 小結

    繪製自定義UI外掛是個細活,必須如加工藝術品一樣有耐心,所以我但凡見到做UI外掛的同仁,都心生佩服。週末閒來無事,根據其他高手的一些程式碼,高仿了一下QQ的登陸介面,很酷吧,呵呵。


    高仿的QQ 2014登陸程式的下載地址:http://download.csdn.net/user/hujkay

    別幹壞事啊~~~

胡楊, Jekkay Hu

2014/4/12










相關推薦

如何使用MFC編寫定義UI介面仿QQ 2014登陸介面範例程式

地址: http://blog.csdn.net/hujkay作者:Jekkay Hu([email protected])關鍵詞:MFC, 編寫異行窗體,自定義UI控制元件,VC++,異形控制元件,高仿QQ登陸介面, 擷取QQ密碼,QQ釣魚時間: 2014/4

定義一個分段控制元件(仿QQ頂部的分段控制元件)

在Android當中並沒有分段控制元件,怎樣去實現一個這樣的分段控制元件,那就要自己去自定義了; 先看一張效果圖: 整體的思路: 1. 設定分段控制元件背景資源 2. 自定義segmentView繼承LinearLayout 3. 設定分段控制元件的屬性(文字的顏色、文

金蝶bos 定義UI介面新增複選框控制元件,並且做業務處理

 /**      * 顯示工程型別      * @author daihao      * 

JmeterJmeter使用AbstractJavaSamplerClient編寫定義流程測試

一、前言       在上一篇部落格中,小編向大家簡單介紹了jmeter 的GUI介面的壓測使用步驟,通過這個步驟我們可以應付大部分的壓測問題了。很多介面都可以通過這種方式來得到壓測報告,根據壓測報告的資料來分析線上真正要使用多少臺機器。       但是有的時

編寫Qt Designer定義控制元件(二)——編寫定義控制元件介面

        既然是控制元件,就應該有介面,預設生成的控制元件類只是一個繼承了QWidget的類,如下: #ifndef LOGLATEDIT_H #define LOGLATEDIT_H #include <QWidget> class LogLat

Swagger 定義UI介面

使用swagger-ui-layergithub上有原始碼,取名為swagger-ui-layer。 歡迎star,fork,commit,也可以隨意修改成自己喜歡的UI風格要使用swagger-ui-layer很簡單 只需要在pom.xml中加入引用就可以了<depe

在Unity3D項目中接入ShareSDK實現安卓平臺微信分享功能(可使用ShareSDK默認UI定義UI

顯示 選項 dev template 腳本 配置文件 all 自己 show   最近公司的大廳要重做,我協助主程一起制作新大廳和新框架,前面制作的編輯器也派上了用場。等全部功能做完後我會再寫一個復盤,這兩天主程在忙於寫熱更新的功能,所以把接入分享SDK功能的任務交給了我,

Hadoop生態圈-hive編寫定義函數

聲明 定義函數 責任 原創 否則 oop -h 作者 AD             Hadoop生態圈-hive編寫自定義函數                                    作者:尹正傑 版權聲明:原創作品,謝絕轉載!否則將追究法律責任。      

百度分享怎麽 定義圖片分享 原創

多功能 有道 amp popu har dia 1.0 例如 IV 我們在應用百度分享插件的時候, 默認如果開啟圖片分享的話,連很多小圖標也分享了,實在惱火! 去掉圖片分享吧,分享效果又不好。。。 如何做到自定義圖片分享呢? 就是預先定義tag標簽 例如: "tag":

如何在MFC定義訊息

訊息對映、迴圈機制是Windows程式執行的基本方式。VC++   MFC   中有許多現成的訊息控制代碼,可當我們需要完成其它的任務,需要自定義訊息,就遇到了一些困難。在MFC   ClassWizard中不允許新增使用者自定義訊息,所以我們必須在程式中新增相應程式碼

Bugly更新定義Ui

appcation 註冊 Beta.autoCheckUpgrade = false;//設定不自動檢查 Beta.upgradeDialogLayoutId = R.layout.layout_upgrade_dialog; 就是根據Ui切圖 把相關的介面和騰訊定義的tag 一一對應 &l

編寫定義的JQuery外掛的幾個注意點

前言 在巨人的肩膀上做事,不出意外的外,你會站的高看得遠!外掛是對功能的封裝,自定義的外掛來擴充套件jQuery,不僅可以促進程式碼的特定風格,而且可以利用jQuery的提供的豐富API,何樂而不為! 一,擴充套件jQuery的形式 在$(jQue

測試報告 之 testNG + Velocity 編寫定義html測試報告

之前用testNG自帶的test-outputemailable-report.html,做出的UI自動化測試報告,頁面不太好看。 在網上找到一個新的報告編寫,自己嘗試了一下,埋了一些坑,修改了輸出時間格式,最終出的結果比以前稍好。 簡單介紹下Velocity 1.不用像jsp那樣編譯成serv

STemwin5.xx底層驅動移植與優化 ------ 編寫定義EmWin Driver參考

首先得說一下為什麼要用STemwin;很多人搞嵌入式的同志應該都想有一個自己的開發環境,每個功能每個模組都自己寫;但是到最後發現無從下手,寫出來的程式碼效率也並不高,因為腦袋裡就沒有這些模組或者功能執行的模式。就像很多人說的“你再怎麼寫,也超不過現有的成熟技術,除非你學會了,在做一些昇華”。 S

vue+ElementUI+德API地址模糊搜尋(定義UI元件)

開發環境描述: Vue.js ElementUI 高德地圖API   需求描述: 在新增地址資訊的時候,我們需要根據input輸入的關鍵字呼叫地圖的輸入提示API,獲取到返回的資料,並根據這些資料生成下拉列表,選擇某一個即獲取當前的地址相關資訊(包括位置名稱、經緯度、街區、城市、id等資

Struts2編寫定義驗證攔截敏感詞彙(十二)

  “兩個蝴蝶飛”特別喜歡"java1234知識分享網"小峰的實用主義,所以本文及其系列文章均是採用實用主義,從專案和程式碼的角度去分析。由於本人經驗有限,嘴皮子不溜,所以學術性,概念性,底層性的知識點暫時不做介紹。文章中有錯誤之處,歡迎拍磚和指點。特別感謝"java1234

Qt編寫定義控制元件屬性設計器

以前做.NET開發中,.NET直接就集成了屬性設計器,VS不愧是宇宙第一IDE,你能夠想到的都給你封裝好了,用起來不要太爽!因為專案需要自從全面轉Qt開發已經6年有餘,在工業控制領域,有一些應用場景需要自定義繪製一些控制元件滿足特定的需求,比如儀器儀表、組態等,而且需要直接使用者通過屬性設計的形式生成匯出控制

雲展網教程 | 如何儲存和應用定義模版主題付費使用者功能

付費使用者可以自定義模板內容,比如工具欄按鈕,工具欄色彩、背景圖片、背景音樂等。對於自定義的模板可以作為主題儲存下來,應用到另一本雜誌上哦。 個人專業版可以儲存1個主題,企業黃金版可以儲存3個,企業白金版儲存5個主題 儲存主題: 選擇基本的模板。如:經典演繹、精簡主義等模板

hive報錯編寫定義函式匯入依賴報錯 Missing artifact jdk.tools:jdk.tools:jar:1.6

少了一個jar包 <dependency> <groupId>jdk.tools</groupId> <artifactId>jdk.tools</artifactId> <version>1.

MFC定義訊息過程

 這幾天接觸一個MFC自定義訊息,但是之前沒用過,犯了一個低階錯誤,粘貼出來供大家參考。  下圖是Windows訊息圖示: 有使用者自定義訊息的一些範圍。以一個具體的例子介紹使用方法:  第一步:本人定義一個訊息