以這么說現在的人越來越妖精了,本來軟件嗎,要的是簡單穩定實用,但是看現在的趨勢是越來越多人注重界面的美化和和效果。比如IM類軟件,QQ,飛信還有土的掉渣的MSN等,前兩天看了一下YahooUI,覺得不錯,ICQ的界面也可以。Windows上界面技術基本都是DirectUI或者近似於DirectUI,而迅雷7使用了WPF做界面,很漂亮,雖然有很多bug,不過可以理解。WPF估計是未來donet平台的主流開發技術了。這樣做就給用戶慣了個壞毛病,如果你的軟件不夠漂亮,就會引來很多非議或者干脆扔掉不用。呵呵, 沒有辦法。其實我的工作本身和界面美化沒什么關系,純粹出於興趣。研究過很多流行的庫,不過問題是開源的很難作出好的效果,效果不錯的卻不開源,當然我不是說不能用純win32或者MFC做出牛X的界面哈,只是一種權衡而已,國內現在有很多公司比如UIPower,UIEasy還有直接叫DirectUI的公司,都是收費的,而且價格不是一般的貴。記得在東軟的時候,項目中買了一個Skin++的授權,MD7千一個,呵呵。其實Skin++先前版本的原理很簡單,采用的是子類化和鈎子而已,當然這也是Win32窗體系列美化的經典做法了。如果哪位哥們有興趣可以聯系我,我們也開發個,而且免費。呵呵。
Ok,廢話少說,回到正題上來吧,說說Juce,這是個很不錯的庫,源碼非常簡練,而且注釋完備,很容易看懂,整個體系就是DirectUI的思路,我一直覺得這東西就是一個精簡版的Qt。我不得不說Jules大哥是個牛人也是好人,有什么問題一封郵件,他立馬回你,而且Juce社區國外用戶很活躍,Juce庫也不斷地完善的和強大。聽Jules大哥說,會加入Skin的功能,Great!
來看第一個例子,我們給他取個名字叫“SuperJucer”吧,該例子的功能就是利用png文件創建一個不規則窗口,估計大家對這個很熟悉了,想想QQ寵物哈,一個小企鵝笨笨的在你的工具欄走來走去,是不是很有意思。而該類就是一個超人叔叔,出現在你的桌面上,沒有windows土里吧唧的邊框和XXX按鈕,哈哈!
先看圖片哈:這就是我們要制作的窗口,超人叔叔。
第二個圖片:景甜妹妹
Ok,素材准備好了,我們就用這兩幅圖片做個異形窗口哈:
第一步: 在VS2008中創建一個Win32的空項目,取名SuperJucer,創建好之后,該工程下面只有三個空的文件夾:header,source,resource. 要的就是干凈。
第二步: 添加兩個文件SuperJucer.h和SuperJucer.cpp.這就是我們的代碼文件。
第三步:設置包含路徑及鏈接庫路徑,請看我第一篇的翻譯哈。
第四步:在頭文件SuperJucer.h中添加以下類:
- #ifndef __SUPERJUCER__
- #define __SUPERJUCER__
- #include "../../juce.h"
- namespace ProjectInfo
- {
- const char* const projectName = "SuperJucer";
- const char* const versionString = "1.0.0";
- const int versionNumber = 0x10000;
- }
- //==============================================================================
- class MainAppWindow : public Component
- {
- public:
- //==============================================================================
- MainAppWindow();
- ~MainAppWindow();
- void closeButtonPressed();
- virtual void paint (Graphics& g);
- void mouseDown (const MouseEvent& e)
- void mouseDrag (const MouseEvent& e)
- juce_UseDebuggingNewOperator
- private:
- MainAppWindow (const MainAppWindow&);
- MainAppWindow& operator= (const MainAppWindow&);
- ComponentDragger dragger;
- Image* m_testWindowBK;
- };
- #endif // __SUPERJUCER__
解釋如下:
- #include "../../juce.h"
- 這個就是包含juce庫文件,按照文檔說明,一般這行應放在stdafx.h中,理由很簡單,就是這個是全局要用的文件。
- class MainAppWindow : public Component
- 這行就是創建一個窗口類,繼承Component, Component是Juce的窗體基類。暫時知道就可以了,我會翻譯后續文檔。到時就明白。
- void closeButtonPressed();
- virtual void paint (Graphics& g);
- void mouseDown (const MouseEvent& e)
- void mouseDrag (const MouseEvent& e)
- 這幾行就是實現一些窗口常用的事件處理函數,需要關閉窗口所以,所以要相應closeButtonPressed這個函數,要移動和拖拽窗口所以mouseDown和mouseDrag需要的。
- 而paint函數就是繪制函數,這個更需要了,因為我們需要把圖片繪制在窗體上,而該函數就是干這事的,至於什么時候調用,怎么調用這事框架關心的,暫時可以不管。
- juce_UseDebuggingNewOperator
- 這一行的意思是允許調new操作符,如果編寫過mfc程序,這個就好理解,你經常會在mfc文件中看到,#define _DEBUG_NEW_ NEW 類似的語句,這行就是這個功能。作用就是便於檢查內存泄露或者其他調試功能。
- ComponentDragger dragger;
- 負責窗體拖拽
- Image* m_testWindowBK;
- 保存背景圖片,在程序啟動的時候加載一次背景圖片,不要放在paint函數中加載哈,因為磁盤IO影響性能:)
第五步 實現文件
- #include "MainWindow.h"
- MainAppWindow::MainAppWindow()
- : Component (JUCEApplication::getInstance()->getApplicationName())
- {
- centreWithSize (500, 400);
- setVisible (true);
- addToDesktop( ComponentPeer::windowIsTemporary | ComponentPeer::windowIsResizable , NULL );
- m_testWindowBK = ImageFileFormat::loadFrom( File( "f://Program//juce//1.png") );
- }
- MainAppWindow::~MainAppWindow()
- {
- delete m_testWindowBK ;
- m_testWindowBK = NULL;
- }
- void MainAppWindow::closeButtonPressed()
- {
- JUCEApplication::getInstance()->systemRequestedQuit();
- }
- void MainAppWindow::paint( Graphics& g )
- {
- if (isOpaque())
- g.fillAll (Colours::white);
- else
- g.fillAll (Colours::blue.withAlpha (0.0f));
- g.drawImage( m_testWindowBK, 0, 0, 256,256, 0,0, 256,256 );
- }
解釋如下:
- centreWithSize (500, 400);
- 是窗口出於桌面的正中,並且設置其大小為500*400
- setVisible (true);
- 是窗口可見
- addToDesktop( ComponentPeer::windowIsTemporary | ComponentPeer::windowIsResizable , NULL );
- 將窗口添加到桌面,這里很有意思,因為MainAppWIndow窗口是直接繼承Component類,該類並不知道其父窗口是誰,所以你必須強行將他加到桌面系統的窗口隊列中。如果沒有這句,雖然進程在但是看不到窗口。
- m_testWindowBK = ImageFileFormat::loadFrom( File( "f://Program//juce//1.png") );
- 加載文件,ImageFileFormat是個封裝數據流或是文件,或是流到Image的類,直接這樣就可以加載文件,是不是很類似Gdi+中的Image::FromImage。呵呵。
繪制部分是最重要的,看代碼:
- if (isOpaque())
- 判斷該窗口是否透明,真是不透明,假是透明。怪異。
- g.fillAll (Colours::white);
- 如果不透明,就直接填充白色
- else
- g.fillAll (Colours::blue.withAlpha (0.0f));
- 如果透明,就填充顏色藍色,並且將它透明度設為0.0f,1.0是不透明哈。目的就是讓窗口本身透明。哈哈,至於什么色無所謂了。主要是alpha通的為0
- g.drawImage( m_testWindowBK, 0, 0, 256,256, 0,0, 256,256 );
- 這是吧剛才的圖片畫上去,和Gdi+中的一致。
編譯運行:看結果:
是不是很帥:) 再看看景甜妹妹的效果:
綠色的我的桌面背景哈。
當然可以用在MFC中通過UpdateLayerAttribute函數也可以達到這個效果。但是我覺得有兩個缺點:
第一:如果你繪制了png圖片,再繪制別的非png元素,該函數會失效
第二:也可以設置遮罩色混合,不過會出現毛邊,這是個很惡心的問題。
Juce做的很帥,這只是它小功能之一,還有很多。后續我會放上demo。
回家吃飯了,有空再繼續。。。。
文中有些自己的理解,如果不對的地方,請給我提出來,但是不能說臟話哈,理解,理解。。。。