码迷,mamicode.com
首页 > Windows程序 > 详细

Windows-定制应用程序外观

时间:2016-06-03 19:40:37      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:

Windows-定制程序外观
简介:介绍常用的应用程序外观属性的操作
一 修改应用程序窗口的外观
1.在窗口创建之前修改
需要在框架窗口的CMainFrame::PreCreateWindow函数中进行操作。
添加如下代码,可以更改窗口的大小和标题

#if 1
    cs.cx = 400;
    cs.cy = 300;
    //设置自定义标题的两种方法
    //cs.style &= ~FWS_ADDTOTITLE;
    cs.style = WS_OVERLAPPEDWINDOW;
    cs.lpszName = _T("chengzhi");
#endif

2.在窗口创建之后修改
需要在CMainFrame::OnCreate函数中操作
添加如下代码,去掉程序标题(文档标题),

#if 1
    //窗口创建之后改变外观
    SetWindowLong(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
#endif

如果想要在已有的窗口风格的基础上修改可以使用下面的代码
GetWindowLong函数和SetWindowLong相对应

#if 1
    //在窗口创建之后去掉窗口的最大化按钮
    SetWindowLong(m_hWnd, GWL_STYLE, GetWindowLong(m_hWnd, GWL_STYLE) & ~WS_MAXIMIZEBOX);
#endif

二 修改窗口的光标,图标和背景
1.在窗口创建之前修改
需要在CMainFrame::PreCreateWindow函数中操作
方法一:自己定义一个窗口类并注册,但是不建议这种方法,太麻烦了。

#if 1
    //不建议使用的方法,改变图标,光标等属性
    WNDCLASS ws;
    ws.cbClsExtra = 0;
    ws.cbWndExtra = 0;
    ws.hbrBackground = static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
    ws.hCursor = LoadCursor(nullptr, IDC_HELP);
    ws.hIcon = LoadIcon(nullptr, IDI_ERROR);
    ws.hInstance = AfxGetInstanceHandle();
    ws.lpfnWndProc = ::DefWindowProc;
    ws.lpszClassName = _T("chengzhi");
    ws.lpszMenuName = nullptr;
    ws.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&ws);

    cs.lpszClass = _T("chengzhi");
#endif

注意:在框架类中只能修改图标,如果要修改背景和光标则需要找View类中操作。
在CStyleView::PreCreateWindow中设置新的窗口类,来修改背景和光标

#if 1
    cs.lpszClass = _T("chengzhi");
#endif

方法二:使用全局函数AfxRegisterWndClass
在框架类中修改图标

#if 1
    //建议使用的方法
    cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, 0, 0, LoadIcon(nullptr, IDI_WARNING));
#endif

在View类中修改背景和光标

#if 1
    //在view中修改客户区中的属性 
    cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, LoadCursor(nullptr, IDC_CROSS), static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
#endif

2.在窗口创建之后修改
在框架类的CMainFrame::OnCreate函数中修改图标属性,具体的API大家可以查看MSDN的帮助:https://msdn.microsoft.com/library

#if 1
    //窗口创建之后改变外观
    SetWindowLong(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
#endif

在View类中修改背景和光标属性

#if 1
    //在视图窗口创建完毕之后设置背景和鼠标指针的图标
    SetClassLong(m_hWnd, GCL_HBRBACKGROUND, (LONG)GetStockObject(BLACK_BRUSH));
    SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)LoadCursor(nullptr, IDC_HELP));
#endif

三 切换应用程序图标
既然是是切换应用程序的图标,那就要在框架类中操作了
先定义一个图标数组

private:
    //存储图标的数组
    HICON m_hIcons[3];

在CMainFrame::OnCreate函数中切换,MAKEINTRESOURCE宏将指定的ID转换成字符串

#if 1
    //初始化图标数组,我们分别使用了3种方法
    m_hIcons[0] = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON1));

    //需要在这个函数的.cpp文件中声明theApp全局对象
    //extern CStyleApp theApp;

    m_hIcons[2] = LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDI_ICON3));

    //设置定时器,id = 1, 定时1000ms,1s切换一个图标
    SetTimer(1, 1000, nullptr);
    //初始化就设置第一幅图标
    SetClassLong(m_hWnd, GCL_HICON, (LONG)m_hIcons[0]);
#endif 

为框架类添加定时器WM_TIMER的事件响应
在 CMainFrame::OnTimer响应函数中添加如下代码:

#if 1
    //因为初始化显示的是第一幅,所以这里设置index = 1,而不是0
    static int index = 1;
    //设置App图标
    SetClassLong(m_hWnd, GCL_HICON, (LONG)m_hIcons[index]);
    //使用取模运算, 将index限定在0-2之内
    index = (++index) % 3; 
#endif

四 工具栏(ToolBar)编程
1.注意:ToolBar中的ID对应于菜单栏中的菜单项的ID,我们一般都是先开发菜单栏,然后将常用的菜单项操作提供到工具栏中。

2.创建ToolBar
先看看它的继承层次
技术分享
创建工具栏仍然需要在框架类中创建
(1).创建工具栏资源
自己创建一个类似系统那样的位图图片即可

(2).构造CToolBar对象

private:
//自定义的新的工具栏
    CToolBar m_newToolBar;

(3).Create()/CreateEx(),LoadToolBar

#if 1
    //创建自定义工具栏
    if (!m_newToolBar.CreateEx(this,
        TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER
        | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
        !m_newToolBar.LoadToolBar(IDR_TOOLBAR1)) {

        TRACE0("未能创建工具栏\n");
        return -1;      // 未能创建
    }
    //设置工具栏可以停靠
    m_newToolBar.EnableDocking(CBRS_ALIGN_ANY);
    //设置主框架窗口可以被停靠
    EnableDocking(CBRS_ALIGN_ANY);
    //停靠工具栏
    DockControlBar(&m_newToolBar);
#endif

3.添加菜单项来管理工具栏
添加一个菜单项,并添加事件响应,在响应函数中添加入下代码

void CMainFrame::OnShowMyToolBar()
{
#if 0
    //复杂的显示方法,而且不能在上次显示的地方重新显示
    if (m_newToolBar.IsWindowVisible()) {
        m_newToolBar.ShowWindow(SW_HIDE);
    }
    else {
        m_newToolBar.ShowWindow(SW_SHOW);
    }
    //框架窗口上的活动对象会受到布局变动的通知
    RecalcLayout();
    DockControlBar(&m_newToolBar);
#endif

#if 1
    //简单的方法,在上次隐藏的地方重新显示
    ShowControlBar(&m_newToolBar, !m_newToolBar.IsWindowVisible(), FALSE);
#endif

}

我们完善这个菜单项,加上复选标记,为刚才添加的菜单项添加命令更新消息,在消息响应函数中这样处理

void CMainFrame::OnUpdateShow(CCmdUI *pCmdUI)
{
    // TODO:  在此添加命令更新用户界面处理程序代码
#if 1
    //设置复选标记的状态
    pCmdUI->SetCheck(m_newToolBar.IsWindowVisible());
#endif
}

五 状态栏(CStatusBar)编程
技术分享
1.在框架类中添加自己的状态栏
框架类已经定义了状态栏成员变量

public:
    CStatusBar  m_wndStatusBar;

添加新的状态指示器标示

//状态栏的指示器数组,资源ID是自己定在字符串资源中的
static UINT indicators[] =
{
    ID_SEPARATOR,           // 状态行指示器
    IDS_TIMER,              //时间指示器
    IDS_PROGRESS,           //进度条指示器
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL,
};

在CMainFrame::OnCreate函数中设置我们的添加的状态指示器显示系统当前时间

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
...
#if 1
    //状态栏显示时间
    SetTimer(1, 1000, nullptr);
    //设置状态栏时间
    CTime t = CTime::GetCurrentTime();
    CString str = t.Format("%H:%M:%S");

    //知道IDS_TIMER的索引是1
    //m_wndStatusBar.SetPaneText(1, str);

    /*不知道状态栏网格的索引*/
    CClientDC dc(this);
    CSize sz = dc.GetTextExtent(str);

    //根据ID获取网格的索引
    int index = m_wndStatusBar.CommandToIndex(IDS_TIMER);

    //设置状态栏网格的宽度
    m_wndStatusBar.SetPaneInfo(index, IDS_TIMER, SBPS_NORMAL, sz.cx);

    //设置网格内容
    m_wndStatusBar.SetPaneText(index, str);
#endif
...

在定时器的响应函数中更新时间,这里只是实例,没有抽取成一个函数,实际开发过程中,不能出现这样的重复代码

void CMainFrame::OnTimer(UINT_PTR nIDEvent) {
...
#if 1
    //设置状态栏时间
    CTime t = CTime::GetCurrentTime();
    CString str = t.Format("%H:%M:%S");

    //知道IDS_TIMER的索引是1
    //m_wndStatusBar.SetPaneText(1, str);

    /*不知道状态栏网格的索引*/
    CClientDC dc(this);
    CSize sz = dc.GetTextExtent(str);

    //根据ID获取网格的索引
    int index = m_wndStatusBar.CommandToIndex(IDS_TIMER);

    //设置状态栏网格的宽度
    m_wndStatusBar.SetPaneInfo(index, IDS_TIMER, SBPS_NORMAL, sz.cx);

    //设置网格内容
    m_wndStatusBar.SetPaneText(index, str);
#endif
...
    CFrameWnd::OnTimer(nIDEvent);
}

2.在状态栏中显示鼠标位置
我们需要得到鼠标的位置,我们就需要在View类中捕获WM_MOUSEMOVW消息进行。
下面提供的几种方法都可以实现功能

void CStyleView::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO:  在此添加消息处理程序代码和/或调用默认值

    CString str;
    str.Format(_T("x = %d, y = %d"), point.x, point.y);

#if 0
    ((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
#endif

#if 0
    //设置状态栏的第一个网格的文本
    ((CMainFrame*)GetParent())->SetMessageText(str);
#endif

#if 0
    ((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(str);
#endif

#if 1
    //获取子孙窗口
    GetParent()->GetDescendantWindow(AFX_IDW_STATUS_BAR)->SetWindowText(str);
#endif 

    CView::OnMouseMove(nFlags, point);
}

6.进度栏编程
技术分享
1.在框架类的OnCreate中创建一个进度栏

#if 0
    //创建水平进度条
    //m_progress.Create(WS_CHILD | WS_VISIBLE, CRect(100, 100, 200, 120), this, 123);

    //创建垂直进度条
    m_progress.Create(WS_CHILD | WS_VISIBLE | PBS_VERTICAL, CRect(100, 100, 120, 200), this, 123);
    m_progress.SetPos(50);
#endif

2.在状态栏中创建进度栏
我们采用发送自定义消息的方式来创建。
1.自定义一个自己用户的消息

MainFrm.h
#define UM_PROGRESS WM_USER + 1

2.添加消息映射声明

// 生成的消息映射函数
protected: 
    afx_msg  LRESULT OnProgress(WPARAM wParam, LPARAM lParam);

3.定义消息映射

MainFrm.cpp
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ...  
    ON_MESSAGE(UM_PROGRESS, &CMainFrame::OnProgress)
    ...
END_MESSAGE_MAP()

4.定义消息响应函数

LRESULT CMainFrame::OnProgress(WPARAM wParam, LPARAM lParam) {
    //在状态栏中显示进度条
    CRect rect;
    m_wndStatusBar.GetItemRect(2, &rect);
    m_progress.Create(WS_CHILD | WS_VISIBLE, rect, &m_wndStatusBar, 123);
    m_progress.SetPos(50);
    return 0;
}

5.让进度栏动起来
在前面设置的定时器的处理函数中,我们增加进度栏的进度百分比,实现动态的效果。

#if 1
    //设置进度栏的步长
    //m_progress.SetStep(1);

    //增加进度栏的步长
    m_progress.StepIt();
#endif

6.为了能在窗口大小改变的时候,保持进度条的位置不变,需要为框架类捕获WM_PAINT消息,在此消息中重新设置进度栏的位置,但是这样出现错误,原因还没找到,大家发现原因可以邮件告诉我,学习了。

void CMainFrame::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    // TODO:  在此处添加消息处理程序代码
    // 不为绘图消息调用 CFrameWnd::OnPaint()
#if 0
    //在状态栏中显示进度条,有问题
    CRect rect;
    m_wndStatusBar.GetItemRect(2, &rect);
    if (!m_progress.m_hWnd) {
        m_progress.Create(WS_CHILD | WS_VISIBLE, rect, &m_wndStatusBar, 123);
    }
    else {
        m_progress.MoveWindow(rect);
    }
    m_progress.SetPos(50);
#endif

}

7.总结
资料:https://yunpan.cn/cSIuhhchmL7ZH 访问密码 bf13
技术分享
欢迎指正

Windows-定制应用程序外观

标签:

原文地址:http://blog.csdn.net/qq_22075977/article/details/51570112

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!