分享
 
 
 

在Windows95/98中实现苹果窗口界面

王朝厨房·作者佚名  2007-01-04
窄屏简体版  字體: |||超大  

高波 马惠业

有没有想过在Windows环境下实现苹果电脑窗口界面的风格?下面就以实现苹果电脑窗口风格为例,进行一次奇妙的旅行。

原 理

仔细观察苹果窗口,发现和Windows窗口的区别主要体现在标题栏和控制按钮(即最小化、恢复、关闭按钮)。所以我们应该把主要精力集中在这两点上,直接对Windows窗口已有的标题栏和控制按钮进行修改。

由于标题栏和控制按钮都属于非客户区,所以关键是获得非客户区的CDC,可以通过GetWindowDC()来获得。GetWindowDC()可以获得整个窗口的CDC,当然也包括非客户区的CDC,得到此CDC后,确定标题条的确切位置,就可以在标题栏上为所欲为了。如图1所示,在标题栏的位置装入一幅位图(截取了苹果窗口的一幅位图),在位图上加上文字标题(此标题具有3D效果,感觉还不错吧,其实就是把相同的字用不同的颜色和坐标写了两次)和控制按钮(实际也是一幅位图,只不过在鼠标单击时显示另一幅位图,看起来就像是一个按钮),由于控制按钮是自己加的,所以要由自己负责单击按钮的处理。到此为止,虽然准备好了窗口的标题栏和按钮,但还没有机会显示。我们知道要在窗口的客户区上画东东,只需响应Windows的客户区重画消息,在此消息处理函数中实现具体的操作。同理,要在非客户区上画东东,也只需响应Windows的非客户区重画消息,在消息处理函数中完成标题栏和按钮的绘制。

具体实现

采用VC6.0在Windows98下实现这种技术。

下面以生成一个苹果界面风格的对话框为例对这种方法进行详细的阐述。

1、用APPWIZARD(应用程序向导)生成一个新的应用程序(SDI与MDI均可),在 RESOURCE VIEW里面添加一个DIALOG资源。

2、添加一个新的对话框类。在ClassWizard中选择添加新类,输入类名CTestDlg并且选取基类CDIALOG。这样就建立起对话框类和对话框资源之间的联系。

3、在RESOURCE VIEW 中加入按钮和标题栏和背景位图。

在主菜单中的INSERT 菜单项下面选择RESOURCE,然后选择添加BITMAP,这样你就可以在RESOURCEVIEW 中看到BITMAP项,下面点击鼠标右键,选择IMPORT,从已有的位图文件中选出苹果风格的按钮和标题栏,并且分别赋予不同的ID。

4、在自己创建的CTestDlg类中添加新的按钮和新的标题栏。

(1)首先在CTestDlg的构造函数中装入位图资源。程序如下:

CTestDlg::CTestDlg(int nID,

CWnd* pParent /*=NULL*/)

: CDialog(nID, pParent)

{

//{{AFX_DATA_INIT(CTestDlg)

// NOTE: the ClassWizard will add

member initialization here

//}}AFX_DATA_INIT

m_bPressed=FALSE;

//load the bitmap of button_down

m_bitmapPressed.LoadBitmap(IDB_BUTTONDOWN);

//load the bitmap of button_up

m_bitmapUnpressed.LoadBitmap(IDB_BUTTONUP);

//load the bitmap of caption

m_bitmapCaption.LoadBitmap(IDB_CAPTION);

//load the bitmap of background

m_bmpBk.LoadBitmap(IDB_BKGROUND);

}

(2)分别得到标题栏和按钮的位置。

首先得到按钮的位置:

void CTestDlg::GetButtonRect(CRect& rect)

{

GetWindowRect(&rect);

// for small caption use SM_CYDLGFRAME

rect.top += GetSystemMetrics(SM_CYFRAME)+1;

// for small caption use SM_CYSMSIZE

rect.bottom =rect.top +GetSystemMetrics

(SM_CYSIZE)-4;

// for small caption use SM_CXDLGFRAME

rect.left =rect.right -GetSystemMetrics

(SM_CXFRAME) -

// for small caption use SM_CXSMSIZE

GetSystemMetrics(SM_CXSIZE))-1;

// for small caption use SM_CXSMSIZE

rect.right =rect.left +GetSystemMetrics

(SM_CXSIZE)-3;

}

然后得到标题栏的位置:

void CTestDlg::GetCaptionRect(CRect &rect)

{

GetWindowRect(&rect);

// for small caption use SM_CYSMSIZE

rect.bottom =rect.top +GetSystemMetrics

(SM_CYSIZE)+3;

}

5.在按钮和标题栏对应的位置上分别画出苹果风格的按钮和标题栏。

首先画出按钮:

void CTestDlg::DrawButton()

{

// if window isn’t visible or is minimized, skip

if (!IsWindowVisible() || IsIconic())

return;

// get appropriate bitmap

CDC memDC;

CDC* pDC = GetWindowDC();

memDC.CreateCompatibleDC(pDC);

memDC.SelectObject(m_bPressed ?

&m_bitmapPressed : &m_bitmapUnpressed);

// get button rect and convert it into non

-client area coordinates

CRect rect, rectWnd;

GetButtonRect(rect);

GetWindowRect(rectWnd);

rect.OffsetRect(-rectWnd.left, -rectWnd.top);

int width,height;

BITMAP *pBitMap;

pBitMap = new BITMAP;

if (m_bPressed)

m_bitmapPressed.GetBitmap(pBitMap);

else

m_bitmapUnpressed.GetBitmap(pBitMap);

width=pBitMap->bmWidth;

height=pBitMap->bmHeight;

// draw it

pDC->StretchBlt( rect.left, rect.top, rect.Width(),

rect.Height(), &memDC, 0, 0,

width,height,SRCCOPY );

memDC.DeleteDC();

ReleaseDC(pDC);

delete pBitMap;

}

然后画出标题栏:

void CTestDlg::DrawCaption()

{

if (!IsWindowVisible() || IsIconic())

return;

// get appropriate bitmap

CDC memDC;

CDC* pDC = GetWindowDC();

memDC.CreateCompatibleDC(pDC);

memDC.SelectObject(m_bitmapCaption);

// get button rect and convert it into non

-client area coordinates

CRect rect, rectWnd;

GetCaptionRect(rect);

GetWindowRect(rectWnd);

rect.OffsetRect(-rectWnd.left, -rectWnd.top);

// draw the caption

int width,height;

BITMAP *pBitMap;

pBitMap = new BITMAP;

m_bitmapCaption.GetBitmap(pBitMap);

width=pBitMap->bmWidth;

height=pBitMap->bmHeight;

pDC->StretchBlt( rect.left, rect.top, rect.Width(),

rect.Height(), &memDC, 0, 0, width,

height, SRCCOPY );

//get the the text of the caption and

draw it with 3D style

pDC->SetBkColor(RGB(209,209,209));

CString caption;

GetWindowText(caption);

caption = “ "+caption+“ ";

rect.OffsetRect(0,4);

//draw the text of the caption with gray color

pDC->SetTextColor(RGB(128,128,128));

pDC->DrawText

(caption,rect,DT_CENTER|DT_VCENTER);

//move the coordinate to left and up

rect.OffsetRect(-1,-1);

pDC->SetBkMode(TRANSPARENT);

//draw the text of the caption with white color

pDC->SetTextColor(RGB(255,255,255));

//255,255,255 128,128,128

pDC->DrawText

(caption,rect,DT_CENTER|DT_VCENTER);

memDC.DeleteDC();

ReleaseDC(pDC);

delete pBitMap;

}

6.处理鼠标点击按钮的消息。

要响应鼠标左键在标题栏上的单击,需要添加相应的消息映射函数。

通过在OnNcLButtonDown中给关闭按钮换一副图像,来实现按钮被按下的效果,同时完成窗口的关闭。

void CTestDlg::OnNcLButtonDown

(UINT nHitTest, CPoint point)

{

if (nHitTest == HTCAPTION)

{

// see if in area we reserved for button

CRect rect;

GetButtonRect(rect);

if (rect.PtInRect(point))

{

m_bPressed = !m_bPressed;

DrawButton();

CDialog::OnCancel();

}

}

CDialog::OnNcLButtonDown(nHitTest, point);

}

7.处理窗口非客户区的重画。

这里主要是对标题栏和按钮的重画。通过ClassWizard给对话框添加非客户区重画的消息映射函数。

void CTestDlg::OnNcPaint()

{

// draw caption first

CDialog::OnNcPaint();

// then draw button on top

DrawCaption();

DrawButton();

}

8.给对话框加上背景,在此为一幅位图:

void CTestDlg::OnPaint()

{

CPaintDC dc(this);

// device context for painting

CDC memDC;

memDC.CreateCompatibleDC(&dc);

memDC.SelectObject(m_bmpBk);

CRect rect, rectWnd

GetWindowRect(rect);

GetClientRect(rect);

int width,height;

BITMAP *pBitMap;

pBitMap = new BITMAP;

m_bmpBk.GetBitmap(pBitMap);

width=pBitMap->bmWidth;

height=pBitMap->bmHeight;

dc.StretchBlt( rect.left, rect.top, rect.Width(),

rect.Height(),

&memDC, 0, 0,width,height, SRCCOPY );

}

至此为止,一个具有苹果窗口风格的对话框就新鲜出炉了!怎么样?味道还不错吧?

但是,如果每次要用到对话框的时候都如此这般,岂不是太...那个了吧!不要惊慌,只需稍做改变就可一劳永逸了。将此对话框的构造函数的说明部分改为下面黑体所示即可,就这么简单。(用黑体表示强调的部分)

CTestDlg::CTestDlg(int nID, CWnd

* pParent /*=NULL*/)

: CDialog(nID, pParent)

{

//{{AFX_DATA_INIT(CTestDlg)

// NOTE: the ClassWizard will add

member initialization here

//}}AFX_DATA_INIT

m_bPressed=FALSE;

m_bitmapPressed.LoadBitmap

(IDB_BUTTONDOWN);

m_bitmapUnpressed.LoadBitmap

(IDB_BUTTONUP);

m_bitmapCaption.LoadBitmap(IDB_CAPTION);

m_bmpBk.LoadBitmap(IDB_BKGROUND);

m_brushButton.CreateSolidBrush

(RGB(192,192,255));

}

以后,凡是用到对话框的时候,在VC的资源编辑器中把对话框设置好,把父类改为此对话框类即可,当然,要把此对话框类包括在你的Project中,图1所示的对话框就是继承于此对话框。

在CMyDialog的.h文件中将CDialog 改为CTestDlg:

Class CMyDialog: public CTestDlg

void CNewapple1Doc::OnDialog1()

{

// TODO: Add your command handler code here

CMyDialog dlg;

dlg.DoModal();

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有