MFC 修改外观和大小,图标、光标、背景

来源:互联网 发布:ap 员工网络 访客网络 编辑:程序博客网 时间:2024/05/16 09:14

转载,觉得非常有用。

 

如何修改MFC AppWizard向导生成的框架程序的外观和大小,修改图标、光标、背景的三种方法。如何增加和删除工具栏按钮,如何给应用程序增加工具栏,如何显示和隐藏工具栏。定制状态栏,在状态栏中添加时钟显示,CTime类及其用法。在状态栏中添加进度条(主窗口产生后立即产生进度条的巧妙思想,不能在OnCreate函数中直接处理,要用到自定义消息的方法)。鼠标坐标显示,在CView中获取状态栏对象的几种方式。如何为应用程序添加启动画面。(孙鑫老师VC课程第九课)


CMainFrame 样式修改
1、在窗口创建前修改:根据多态性原理,在CMainFrame的PreCreateWindow函数中修改。
In a single document interface (SDI) application, the default window style in the framework is a combination of the WS_OVERLAPPEDWINDOW and FWS_ADDTOTITLE styles. FWS_ADDTOTITLE is an MFC-specific style that instructs the framework to add the document title to the window’s caption. To change the window attributes in an SDI application, override the PreCreateWindow function in your class derived from CFrameWnd (which AppWizard names CMainFrame). For example:

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// Create a window without min/max buttons or sizable border
cs.style = WS_OVERLAPPED | WS_SYSMENU | WS_BORDER;

// Size the window to 1/3 screen size and center it
cs.cy = ::GetSystemMetrics(SM_CYSCREEN) / 3;
cs.cx = ::GetSystemMetrics(SM_CXSCREEN) / 3;
cs.y = ((cs.cy * 3) - cs.cy) / 2;
cs.x = ((cs.cx * 3) - cs.cx) / 2;

// Call the base-class version
return CFrameWnd::PreCreateWindow(cs);
}

要改变窗口的名字,必须去掉默认的FWS_ADDTOTITLE 属性

This code creates a main frame window without
2、在窗口创建后修改:OnCreate函数中修改,里面加上函数SetWindowLong
The SetWindowLong function changes an attribute of the specified window. The function also sets a 32-bit (long) value at the specified offset into the extra window memory of a window.

index为GWL_STYLE;样式的意思 其他有
GWL_EXSTYLE Retrieves the extended window styles.
GWL_STYLE Retrieves the window styles.
GWL_WNDPROC Retrieves the address of the window procedure, or a handle representing the address of the window procedure. You must use the CallWindowProc function to call the window procedure.
GWL_HINSTANCE Retrieves the handle of the application instance.
GWL_HWNDPARENT Retrieves the handle of the parent window, if any.
GWL_ID Retrieves the identifier of the window.
GWL_USERDATA Retrieves the 32-bit value associated with the window. Each window has a corresponding 32-bit va

LONG SetWindowLong(
HWND hWnd, // handle of window
int nIndex, // offset of value to set
LONG dwNewLong // new value
);
另外一个对应的函数
The GetWindowLong function retrieves information about the specified window. The function also retrieves the 32-bit (long) value at the specified offset into the extra window memory of a window.

LONG GetWindowLong(
HWND hWnd, // handle of window
int nIndex // offset of value to retrieve
);
2、如何修改光标、图标等
MFC默认的光标、图标是由MFC底层代码完成的。当然,我们是不能修改MFC的底层代码的。
创建之前
而应该:
方法1:
在PreCreateWindow函数,定义一个自己的窗口类
HINSTANCE AfxGetInstanceHandle( );这个函数返回当前应用程序实例的句柄。
DefWindowProc默认的窗口函数。注意,这里用的是全局API函数,前面要有::
菜单不是这个时候加上去的,而是在应用程序类的初始化函数加上去的,所以暂时先设置为NULL
然后注册这个窗口类
改变cs的属性类名为刚刚定义的这个类。
在框架窗口中只能修改图标等没被View覆盖的。
光标修改:应该在View类中的PreCreateWindow修改,将cs属性类名为刚刚定义的这个类。
这个方法麻烦!
方法2:
使用下面这个函数:
LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0 );
nClassStyle 为样式 参看 WndClass的style成员。msdn
在框架类的PreCreateWindow函数中 用它修改图标。
在视图类的PreCreateWindow函数中,用它修改背景、光标、画刷。
创建之后
方法1:
SetClassLong函数
The SetClassLong function replaces the specified 32-bit (long) value at the specified offset into the extra class memory or the WNDCLASSEX structure for the class to which the specified window belongs.

DWORD SetClassLong(
HWND hWnd, // handle of window
int nIndex, // index of value to change
LONG dwNewLong // new value
);
用法查看msdn 注意类型转换。

创建一个不断变化的图标。用定时器和SetClassLong完成,方法如下:

①     通过Insert->Resource-绘制三个图标文件,放在RES文件夹,

②      在CMainFrame中增加图标句柄数组,m_hIcons[3]

 m_hIcons[0]=LoadIcon(AfxGetInstanceHandle(),

MAKEINTRESOURCE是一个宏,它将整数转化为Win32的资源类型

m_hIcons[1]=LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2));需要用到

theAPP对象,故要在文件中声明extern CStyleApp theApp;

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

 ③然后通过Settimer()来设计定时器,实现三张图表的切换

3、获取当前应用程序与实例句柄
AfxGetApp() 它也有个成员是实例句柄
AfxGetInstanceHandle()
4、WM_TIMER消息使用
时间间隔设置 SetTimer()在构造函数里使用。


5、创建自定义工具栏的步骤
Visual C++ provides you with two methods to create a toolbar. To create a toolbar resource using the Resource Editor, follow these steps:
(1)Create a toolbar resource.
(2)Construct the CToolBar object.
(3)Call the Create (or CreateEx) function to create the Windows toolbar and attach it to the CToolBar object.
(4)Call LoadToolBar to load the toolbar resource.

带位图图标的按扭,将常用的菜单命令集合起来供用户使用,它与菜单项的一些命令通过相同的ID号相关联

加入分隔符的方法,向右拖动即可;删除按纽的方法,拖出即可。

②     点击“新的工具栏”菜单时,隐藏工具栏。两种方法:

  方法一:通过Showwindon()来实现二者状态的转换,具体为:

if(m_newToolBar.IsWindowVisible())

{

  m_newToolBar.ShowWindow(SW_HIDE);

}

else

{

  m_newToolBar.ShowWindow(SW_SHOW);

}

再通过RecalcLayout();来进行工具栏位置的调整。

方法二:ShowControlBar(&m_newToolBar,!m_newToolBar.IsWindowVisible(),FALSE);

③将菜单增加复选标记可以通过SetCheck();函数来实现


参看默认生成步骤.
6、状态栏

①Indicator[]数组中有状态栏的信息,  如果要增加分隔栏,只需要增加字符串的字符的ID

②在时间栏显示系统时间:通过Ctime::GetcurrentTimer(),通过Fomat将时间进行格式化,以字符形式输出。

将其设置的时间显示在状态栏中,通过Setpanetext()shixian实现,要改变状态栏窗格的宽度,可以通过Setpameinfo()来实现,而要让时间是动态的,可以通过将Timer()函数放到Ontime响应函数中,记下当前的时间,并显示出来。

7、显示鼠标位置

方法一:

⑴先获取鼠标的位置消息,在View中增加OnMouseMove()处理函数

⑵获取状态栏的地址

⑶通过SetWindowText ()来实现

方法二:((CMainFrame*)GetParent())->SetMessageText(str)来实现

方法三: ((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(str);

方法四: GetDescendantWindow(AFX_IDW_STATUS_BAR)->SetWindowText(str)

8、自定义消息
The WM_USER constant is used by applications to help define private messages, usually of the form WM_USER+X, where X is an integer value.使用:#define UM_PROGRESS WM_USER+1

用MFC向导增加消息响应函数时,其会在三个地方增加代码:

我在一个单文档框架类中添加了一个消息响应函数后,会在MainFrame.h中增加

afx_msg void OnLButtonUp(UINT nFlags, CPoint point);

afx_msg表示为消息响应函数。

protected:
 //{{AFX_MSG(CMainFrame)
 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
 afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
};

在MainFrame.cpp中会增加ON_WM_LBUTTONUP()宏,(命令消息映射宏)通过这个宏就可实现,一旦从消息队列中取出WM_LBUTTONUP消息,就会去调用OnLButtonUp(UINT nFlags, CPoint point);函数

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
 //{{AFX_MSG_MAP(CMainFrame)
 ON_WM_CREATE()
 ON_WM_LBUTTONUP()
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

在MainFrame.cpp中会增加会增加OnLButtonUp(UINT nFlags, CPoint point);的实现。void CMainFrame::OnLButtonUp(UINT nFlags, CPoint point) 
{
 // TODO: Add your message handler code here and/or call default
 
 CFrameWnd::OnLButtonUp(nFlags, point);
}

自定义消息时首先,在头文件中 定义消息:#define UM_PROGRESS WM_USER+X

X为任意整数,并在头文件DECLARE_MESSAGE_MAP()之前,注释宏之后添加

afx_msg void OnProgress();为UM_PROGRESS 消息响应函数
protected:
 //{{AFX_MSG(CMainFrame)
 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
 afx_msg void OnTimer(UINT nIDEvent);
 afx_msg void OnPaint();
 //}}AFX_MSG
 afx_msg void OnProgress();
 DECLARE_MESSAGE_MAP()

再在.cpp文件的BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)与END_MESSAGE_MAP()之间添加 ON_MESSAGE(UM_PROGRESS,OnProgress) 通过 ON_MESSAGE实现 UM_PROGRESS消息与其消息响应函数OnProgress的联系。

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
 //{{AFX_MSG_MAP(CMainFrame)
 ON_WM_CREATE()
 ON_WM_TIMER()
 ON_WM_PAINT()
 //}}AFX_MSG_MAP
 ON_MESSAGE(UM_PROGRESS,OnProgress)
END_MESSAGE_MAP()

最后在.cpp文件中实现OnProgress函数

void CMainFrame::OnProgress()
{
 CRect rect;
 m_wndStatusBar.GetItemRect(2,&rect);
 m_progress.Create(WS_CHILD | WS_VISIBLE ,
  rect,&m_wndStatusBar,123);
 m_progress.SetPos(50);
}

当需要发出UM_PROGRESS消息时,可以通过

SendMessage(UM_PROGRESS);//相当于在SendMessage处直接调用OnProgress
 PostMessage(UM_PROGRESS);//先把UM_PROGRESS放到消息队列中,然后取出响应

9、加入启动画面

  可以通过Project-Component and ->Visual C++ Components->SplashScreen->插入来实现其功能。

原创粉丝点击