飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 3493|回复: 4

给windows换肤(一)

[复制链接]

该用户从未签到

发表于 2006-1-5 13:54:39 | 显示全部楼层 |阅读模式
region.h
这个是我在flipcode上看到的文章,个人觉得简单易懂就拿过来了
版权归作者 Vander Nunes
我只是起一个媒介的作用,希望和我一样弱的菜菜可以有所收获
   修改者   小鱼儿(qxtianlong)
//首先我们来看看头文件,做些声明


#ifndef _REGION_H_

  #define _REGION_H_
  #include <windows.h>

  // app window handle
  HWND hWnd=NULL;

  // region toggle
  bool bRegioned;

  // app window procedure
  LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);

  // window creation helper
  bool MakeWindow(int iWidth, int iHeight);

#endif
//以上别告诉我不懂厄

region.cpp
下面我们看看CPP文件
下面是代码部分
#include "region.h"




// ------------------------------------------------------------------------
// The application entry point
// ------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, \
                   LPSTR lpCmdLine, int nCmdShow)
{
  // -------------------------------------------------
  // create the application window.
  // -------------------------------------------------

  if ( !MakeWindow(320, 240) ) return -1;

  // show window
  ShowWindow(hWnd, SW_SHOW);


  // -------------------------------------------------
  // now just keep the application going...
  // -------------------------------------------------

  MSG mMsg;

  while (1)
  {

    if(PeekMessage(&mMsg, 0, 0, 0, PM_REMOVE))
    {
      // -------------------------------------------------
      // the quit message
      // can arrive at any time from our window procedure.
      // -------------------------------------------------
      if(mMsg.message == WM_QUIT)
      { break; }

      // -------------------------------------------------
      // the common stuff, just translate&dispatch.
      // -------------------------------------------------
      TranslateMessage(&mMsg);
      DispatchMessage(&mMsg);
    }

  }


  // -------------------------------------------------
  // free allocated resources
  // -------------------------------------------------

  DestroyWindow(hWnd);


  // tchau!
  return 0;
}



// ------------------------------------------------------------------------
// Build a basic region and set it to the window.
// ------------------------------------------------------------------------
void RegionMe()
{
  // --------------------------------------------------
  // create an elliptical region.
  // we use a negative starting y coordinate to make
  // the ellipse cover a bit more of the caption.
  // --------------------------------------------------
  HRGN hRegion1 = CreateEllipticRgn(20,-20,190,150);

  // --------------------------------------------------
  // create one more elliptical region in other place.
  // --------------------------------------------------
  HRGN hRegion2 = CreateEllipticRgn(140,100,300,240);

  // --------------------------------------------------
  // combine the two regions to build a new region
  // that will be the sum of the two.
  // the resulting region will be stored in region1,
  // like if we were making something like:
  // hRegion1 = hRegion1 + hRegion2.
  // --------------------------------------------------
  CombineRgn(hRegion1, hRegion1, hRegion2, RGN_OR);

  // --------------------------------------------------
  // assign the region to the window
  // --------------------------------------------------
  SetWindowRgn(hWnd, hRegion1, true);

  // --------------------------------------------------
  // delete the region objects
  // --------------------------------------------------
  DeleteObject(hRegion1);
  DeleteObject(hRegion2);

  // --------------------------------------------------
  // flag just to make sure our app knows about it.
  // --------------------------------------------------
  bRegioned = true;
}



// ------------------------------------------------------------------------
// Remove the region from the window
// ------------------------------------------------------------------------
void UnRegionMe()
{
  // --------------------------------------------------
  // unassign the region
  // --------------------------------------------------
  SetWindowRgn(hWnd, NULL, true);

  // --------------------------------------------------
  // flag just to make sure our app knows about it.
  // --------------------------------------------------
  bRegioned = false;
}



// ------------------------------------------------------------------------
// A Basic, still smart window creation function.
// ------------------------------------------------------------------------
bool MakeWindow(int iWidth, int iHeight)
{
  // our window class
  WNDCLASS wndWc;

  // ---------------------------------------------------------
  // fill window class members
  // ---------------------------------------------------------
  wndWc.style = CS_OWNDC;
  wndWc.lpfnWndProc = (WNDPROC) WndProc;
  wndWc.cbClsExtra = 0;
  wndWc.cbWndExtra = 0;
  wndWc.hInstance = GetModuleHandle(NULL);
  wndWc.hIcon = NULL;
  wndWc.hCursor = LoadCursor(0, IDC_ARROW);
  wndWc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wndWc.lpszMenuName = NULL;
  wndWc.lpszClassName = "w32skin";

  // register class
  if (!RegisterClass(&wndWc)) return false;
  // ---------------------------------------------------------

  // get actual screen resolution
  int iSw = (WORD)GetSystemMetrics(SM_CXSCREEN);       // width
  int iSh = (WORD)GetSystemMetrics(SM_CYSCREEN);       // height

  // make a rectangle on the center of the screen
  RECT rc = { (iSw - iWidth)/2, (iSh - iHeight)/2, iWidth, iHeight };

  // create the window. the spaces on the window title
  // are just to make sure this will be visible when the region
  // is active. just run the app and you'll understand. =)
  hWnd = CreateWindow("w32skin", "       w32skin",
                      WS_OVERLAPPEDWINDOW,
                      rc.left,rc.top, iWidth,iHeight,
                      NULL, NULL, GetModuleHandle(NULL), NULL);

  // return result
  return (hWnd?true:false);
}



// ------------------------------------------------------------------------
// Our application window procedure.
// Here we'll process the messages sent to our application window.
// ------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{

  switch(uMessage)
  {

    case WM_KEYDOWN:
    {
      // ---------------------------------------------------------
      // pressing ESC will finish the app.
      // ---------------------------------------------------------
      switch (wParam)
      {
        case VK_ESCAPE:
          PostQuitMessage(0);
          break;

        case VK_SPACE:
          if (!bRegioned)
            RegionMe();
          else
            UnRegionMe();
      }
      break;
    }

    case WM_PAINT:
    {
      // -------------------------------------------------
      // tell user to press SPACE to toggle region.
      // -------------------------------------------------

      PAINTSTRUCT ps;
      BeginPaint(hWnd,&ps);

      TextOut(ps.hdc, 115,90, "Press SPACE", 11);

      EndPaint(hWnd,&ps);

      break;
    }

    case WM_DESTROY:
    {
      // ---------------------------------------------------------
      // closing the window will finish the app.
      // (the quit message will be read by our main loop)
      // ---------------------------------------------------------
      PostQuitMessage(0);
      break;
    }


  }

  // ---------------------------------------------------------
  // call the default window procedure to keep things going.
  // ---------------------------------------------------------
  return DefWindowProc(hWnd,uMessage,wParam,lParam);
}

好了以上文件完全可编译,在XPSP2+VS2003下通过
注意:只要去掉我的不正规的文字说明就可以了,别告诉我你不会哇~~

[ 本帖最后由 qxtianlong 于 2006-1-6 17:42 编辑 ]
PYG19周年生日快乐!

该用户从未签到

 楼主| 发表于 2006-1-5 13:55:16 | 显示全部楼层
下面我们来解释一下上面的代码
首先头文件中
HWND hWnd=NULL;
代表窗口的句柄,就是一个标识
bool bRegioned;
代表一个状态量(一个开关)
后面会看到
程序根据bRegioned的值,做相应的处理
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
这个是一个事件循环函数的声明(回调函数)
bool MakeWindow(int iWidth, int iHeight);
这个是一个基本的定义一个类和建立一个窗口的函数的声明
在后面我们会看到他的具体定义
不错嘛~~头文件部分我们就介绍完了,其实你也可以直接写在CPP文件中的,怎么样随你便,只要能
达到效果就可以了
---------------------------------------------------------------------------------------------------
下面我们来解释一下CPP文件中的主要内容
---------------------------------------------------------------------------------------------------
#include "region.h"
这句的作用是包含前面的头文件
我们来看看MakeWindow()函数的定义
bool MakeWindow(int iWidth, int iHeight)
{
  // 首先定义一个类,这是一个比较老的版本了,新的版本是WNDCLASSEX使用起来大同小异
  WNDCLASS wndWc;

  // ---------------------------------------------------------
  // 填充类成员
  // ---------------------------------------------------------
  wndWc.style = CS_OWNDC;//似乎是windows属性样式的标志
  wndWc.lpfnWndProc = (WNDPROC) WndProc;//指向回调函数的指针
  wndWc.cbClsExtra = 0;
  wndWc.cbWndExtra = 0;
  wndWc.hInstance = GetModuleHandle(NULL);//获得当前应用程序实例
  wndWc.hIcon = NULL;//图标
  wndWc.hCursor = LoadCursor(0, IDC_ARROW);//光标
  wndWc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//背景画刷
  wndWc.lpszMenuName = NULL;//菜单
  wndWc.lpszClassName = "w32skin";//类名

  // 注册类,失败则返回false,这个版本也比较老,新版本为RegisterClassEx()
  if (!RegisterClass(&wndWc)) return false;
  // ---------------------------------------------------------

  // get actual screen resolution
  int iSw = (WORD)GetSystemMetrics(SM_CXSCREEN);       // width
  int iSh = (WORD)GetSystemMetrics(SM_CYSCREEN);       // height
上面两句为调用(API)GetSystemMetrics获取屏幕大小(像素级)
SM_CXSCREEN,SM_CYSCREEN分别为宽和高
  // make a rectangle on the center of the screen
  RECT rc = { (iSw - iWidth)/2, (iSh - iHeight)/2, iWidth, iHeight };
上面为定义一个大小为iWidth,iHight的矩形,在这里就理解为大小为iWidth,iHeight的窗口
RECT结构原型如下
typedef struct _RECT {
  LONG left;
  LONG top;
  LONG right;
  LONG bottom;
} RECT, *PRECT;
似乎left,top分别代表左上角的x,y坐标,right,bottom分别代表右下角的x,y坐标
那么上面的左上角坐标就为
(iSw - iWidth)/2, (iSh - iHeight)/2
怎么样还是容易理解的吧
  // create the window. the spaces on the window title
  // are just to make sure this will be visible when the region
  // is active. just run the app and you'll understand. =)
  hWnd = CreateWindow("w32skin", "       w32skin",
                      WS_OVERLAPPEDWINDOW,
                      rc.left,rc.top, iWidth,iHeight,
                      NULL, NULL, GetModuleHandle(NULL), NULL);
上面为创建一个窗口
这个也是一个比较老的版本,新版本CreateWindowEx()
第一个参数为类名
第二个参数为窗口标题名
第三个参数为窗口外观风格
第四个参数为窗口左上角坐标X
第五个参数为窗口左上角坐标Y
第六个参数为窗口的宽
第七个参数为窗口的高
第八个参数为是否有父窗口NULL代表没有父窗口,桌面就是父窗口
第九个参数为是否有菜单NULL为没有菜单
第十个参数为应用程序实例
第十一个参数为一些高级特征通常为NULL
  // return result
  return (hWnd?true:false);
这一句为窗口创建成功返回true,否则返回false
}

下面我们看看主要的绘制部分
void RegionMe()
{
  // --------------------------------------------------
  // create an elliptical region.
  // we use a negative starting y coordinate to make
  // the ellipse cover a bit more of the caption.
  // --------------------------------------------------
  HRGN hRegion1 = CreateEllipticRgn(20,-20,190,150);

  // --------------------------------------------------
  // create one more elliptical region in other place.
  // --------------------------------------------------
  HRGN hRegion2 = CreateEllipticRgn(140,100,300,240);
  以上是创建两个圆,CreateEllipticRgn原型如下:
HRGN CreateEllipticRgn(
  int nLeftRect,   // x-coord of upper-left corner of rectangle
  int nTopRect,    // y-coord of upper-left corner of rectangle
  int nRightRect,  // x-coord of lower-right corner of rectangle
  int nBottomRect  // y-coord of lower-right corner of rectangle
);

  // --------------------------------------------------
  // combine the two regions to build a new region
  // that will be the sum of the two.
  // the resulting region will be stored in region1,
  // like if we were making something like:
  // hRegion1 = hRegion1 + hRegion2.
  // --------------------------------------------------
  CombineRgn(hRegion1, hRegion1, hRegion2, RGN_OR);
以上为合并两个区域大小为hRegion1,CombineRgn原型如下:
int CombineRgn(
  HRGN hrgnDest,      // handle to destination region
  HRGN hrgnSrc1,      // handle to source region
  HRGN hrgnSrc2,      // handle to source region
  int fnCombineMode   // region combining mode
);
其中fnCombineMode可以为以下的值

Value                      Description
RGN_AND         Creates the intersection of the two combined regions.
RGN_COPY       Creates a copy of the region identified by hrgnSrc1.
RGN_DIFF        Combines the parts of hrgnSrc1 that are not part of hrgnSrc2.
RGN_OR           Creates the union of two combined regions.
RGN_XOR         Creates the union of two combined regions except for any overlapping areas.
  // --------------------------------------------------
  // assign the region to the window
  // --------------------------------------------------
  SetWindowRgn(hWnd, hRegion1, true);
这句就是设置hRegion1区域,SetWindowRgn原型如下:
int SetWindowRgn(
  HWND hWnd,     // handle to window
  HRGN hRgn,     // handle to region
  BOOL bRedraw   // window redraw option
);
hWnd
[in] Handle to the window whose window region is to be set.
hRgn
[in] Handle to a region. The function sets the window region of the window to this region.
If hRgn is NULL, the function sets the window region to NULL.

bRedraw
[in] Specifies whether the system redraws the window after setting the window region. If bRedraw is TRUE, the system does so; otherwise, it does not.
Typically, you set bRedraw to TRUE if the window is visible.


  // --------------------------------------------------
  // delete the region objects
  // --------------------------------------------------
  DeleteObject(hRegion1);
  DeleteObject(hRegion2);
上面为释放对象
  // --------------------------------------------------
  // flag just to make sure our app knows about it.
  // --------------------------------------------------
  bRegioned = true;
设置bRegioned的状态为true
}
PYG19周年生日快乐!

该用户从未签到

 楼主| 发表于 2006-1-5 13:55:31 | 显示全部楼层
剩下的这个
void UnRegionMe()
{
  // --------------------------------------------------
  // unassign the region
  // --------------------------------------------------
  SetWindowRgn(hWnd, NULL, true);
设置窗口区域为空
  // --------------------------------------------------
  // flag just to make sure our app knows about it.
  // --------------------------------------------------
  bRegioned = false;
设置bRegioned状态为false
}
剩下的就很好说了,进入消息循环,根据是否按了空格键来改变窗口的皮肤
按一次空格键bRegioned的状态就会随之改变
也不知道大家能不能看懂,呵呵
我是根据我的理解写的,不对之处请批评指教
PYG19周年生日快乐!

该用户从未签到

发表于 2006-6-6 10:04:32 | 显示全部楼层
简单易懂。。。。。刚睡了一个小时,回来还是看不懂
PYG19周年生日快乐!

该用户从未签到

发表于 2006-6-6 10:43:57 | 显示全部楼层
支持一下。。。
PYG19周年生日快乐!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表