涉及知识点:(喜欢的点个关注,谢谢支持)
- 如何实现启动软件时出现一个欢迎画面。
- 如何在欢迎画面后实现一个用户登录界面。
- 如何在对话框窗口上动态添加一个文本(CStatic),并改变文本的字体、字的大小等。
- 如何改变对话框以及对话框上的控件的背景颜色。
- 获取对话框上的控件的窗口指针的两种方式。
一、如何创建一个单文档应用程序的启动欢迎画面?
1)、新建一个MFC的单文档应用程序的工程(工程名:Demo),在“资源视图”中添加一个BitMap资源。该bitmap将用来作为启动时的欢迎画面。
2)、在"类向导"中添加一个MFC类,该类将用于实现启动画面,类名为:CSplashWnd, 父类继承自CWnd。
3)、在新增的CSplashWnd类的头文件 CSplashWnd.h中:
public:
CBitmap m_bitmap;
void Create(UINT nBitmapID);
afx_msg void OnPaint();
4)、在新增的CSplashWnd.cpp源文件中定义create()函数,并重写WM_PAINT消息的响应即 OnPaint()函数,WM_PAINT消息是在启动画面将被绘制时发送给该窗口的。
void CSplashWnd::Create(UINT nBitmapID)
{
m_bitmap.LoadBitmap(nBitmapID); //使用传参的bitmap的资源id
BITMAP bitmap;
m_bitmap.GetBitmap(&bitmap);
CreateEx(0, AfxRegisterWndClass(0, AfxGetApp()>LoadStandardCursor(IDC_ARROW)),
NULL, WS_POPUP | WS_VISIBLE, 0, 0, bitmap.bmWidth, bitmap.bmHeight, NULL, NULL);
}
void CSplashWnd::OnPaint()
{
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CWnd::OnPaint()
CPaintDC dc(this); // device context forpainting
BITMAP bitmap;
m_bitmap.GetBitmap(&bitmap);
CDC dcComp;
dcComp.CreateCompatibleDC(&dc); //创建当前dc的兼容dc
dcComp.SelectObject(&m_bitmap);
// draw bitmap
dc.BitBlt(0, 0, bitmap.bmWidth, bitmap.bmHeight, &dcComp, 0, 0, SRCCOPY);
}
5)、我们的框架窗口创建时会调用Create函数,所以我们将欢迎画面的创建动作放在该函数内,使其最先显示。在CMainFrame类中:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
CSplashWnd wndSplash; //创建启动窗口类的实例
wndSplash.Create(IDB_LAUNCH);
wndSplash.CenterWindow();
wndSplash.UpdateWindow(); //send WM_PAINT
Sleep(3000); //让主线程暂停3秒,显示欢迎画面
wndSplash.DestroyWindow(); //销毁初始画面窗口
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
... ...//省略中间原来代码
retrun 0
}
至此,我们的启动软件时的欢迎画面就做好了。
二、如何创建一个单文档应用程序的用户登录界面?
1)、继续,在Demo工程中新建一个对话框资源,然后将对话框属性中的border改为NONE(我喜欢无边框的效果)。
2)、在该对话框上添加两个编辑框EditCtrl控件和两个按钮Button控件,更改他们的属性和ID值
3)、为该登录对话框资源添加一个关联的类,类名为:CLoginDlg,父类继承自CDialogEx。
4)、在新增的对话框类的头文件CLoginDlg.h 头文件中:
public:
//画刷、字体等需要声明为类内的成员变量,若声明局部变量,当生命周期结束时,画刷所
//绘制的内容将恢复默认
CBrush m_brush;//画刷
CFont* m_pFont; //字体,声明为类内成员
CStatic *m_pStaText;//登录界面的标头
5)、在新增的对话框类的源文件CLoginDlg.cpp中:
CLoginDlg::CLoginDlg(CWnd* pParent /*=nullptr*/) //在CLoginDlg的构造函数中做初始化
: CDialogEx(IDD_LOGIN, pParent){
m_pFont = NULL;
m_pStaText = NULL;
}
CLoginDlg::~CLoginDlg() { //在析构函数中,做资源的释放
if (m_pFont) {
delete m_pFont;
m_pFont = NULL;
}
if (m_pStaText) {
delete m_pStaText;
m_pStaText = NULL;
}
}
//重写虚函数OnInitDialog(),在该函数中增加以下代码:
//创建一个画刷和一个字体。注意,画刷和字体的对象需要声明为CLoginDlg类内
//的成员,否则创建完成后由于生命周期结束,被设置字体的部分将恢复成默认字体。
BOOL CLoginDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();// TODO: 在此添加额外的初始化
m_brush.CreateSolidBrush(RGB(151, 211, 238)); //创建一个画刷
m_pFont = new CFont; //创建一个字体
m_pFont->CreateFontW(22, 10, 0, 0, 400/*正常粗细*/, 0, 0, 0, GB2312_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"宋体");CRect rtDlg, rtStatic; //添加用户登录界面的标头
GetWindowRect(rtDlg); //获取对话框的矩形位置作为摆放参照物,此函数获取的矩形位 置是相对于屏幕左上角的。
ScreenToClient(&rtDlg); //转换为对话框上的客户区坐标CString sStatic = _T("制图、工艺、编程---任务派发管理系统");
int nEdgeWidth = 15;//距离边界的宽度留白
int nStaticWidth = 60;//文本的宽度
int nStaticHeight = 40;//高度
rtStatic.top = rtDlg.top + nEdgeWidth;
rtStatic.bottom = rtDlg.top + nStaticHeight;
rtStatic.left = rtDlg.left + nEdgeWidth;
rtStatic.right = rtDlg.right - nEdgeWidth;m_pStaText = new CStatic;//动态创建文本
m_pStaText->Create(sStatic, WS_CHILD | WS_VISIBLE |SS_CENTER/*文本在矩形中间 显示*/, rtStatic, this, 100);
m_pStaText->ShowWindow(SW_SHOW);GetDlgItem(100)->SetFont(m_pFont);
//或者使用FromHandle(m_pStaText->m_hWnd)->SetFont(m_pFont);return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
6)、接着,我们为UI做一些简单的美化工作,改变控件颜色字体等。
(知识)改变控件(文本static、编辑框edit、按钮button、等等)的颜色其实有两种方式:
- 第一种就是在控件本身的类内,自身绘制时修改其属性:颜色、字体、等等。这就要求我们自己创建一个类,并在类内对这些行为做定义,(欢迎关注,后续文章会系统讲解并进行分类封装)
- 第二种就是在使用时,调用窗口创建的时候在主窗口对其进行绘制时进行修改。我们这里演示的是第二种。
- 在对话框中对于对话框和相关包含的控件的着色动作是响应WM_CTLCOLOR这个消息的,所以我们对捕获这个消息时的动作进行定义便可改变对应的控件的属性。重写这个消息的响应函数,其参数中就自带了一个绘图时的dc,是与当前dlg窗口关联的dc。
- 绘制时它会将该对话框上所属的所有的需要绘制的控件按ID资源逐一绘制,我们只需要判断,当前所绘制的是我们想改变颜色的那个控件,就让dc使用我们提供的画刷。
HBRUSH CLoginDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何特性
//CTLCOLOR_DLG 对话框背景色 CTLCOLOR_STATIC 为你要改变的控件ID
if (nCtlColor == CTLCOLOR_DLG || nCtlColor == CTLCOLOR_STATIC) {
//CDC::SetBkColor 设置当前关联dc的窗口的背景色
pDC->SetBkColor(RGB(151, 211, 238));
return (HBRUSH)m_brush.GetSafeHandle(); //返回淡蓝色刷子的句柄资源
}
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return hbr;
}
7)、完善用户登录界面的登录机制
//添加“登录按钮”的点击消息响应函数,注意你的“用户名”和对应的“密码”可以从SQL数据库中获取,也可以使用一个本地的配置文件,或者服务器上的配置文件。这里我们只说原理,忽略业务逻辑。
void CLoginDlg::OnBnClickedLogin()
{
// TODO: 在此添加控件通知处理程序代码
USES_CONVERSION;
UpdateData(true);
CString sUser, sPasWrd{ _T("") }; //UI列表框获取的内容
GetDlgItemText(IDC_USER, sUser);
GetDlgItemText(IDC_PASWRD, sPasWrd);
if ("" == sUser || "" == sPasWrd){
MessageBox(L"不能为空", L"温馨提示", MB_OK);
return;
}
if ("数据库内获取的用户名" == sUser || "对应的密码" == sPasWrd) {
CDialogEx::OnOK();//关闭对话框,进入
} else {
MessageBox(L"用户或密码错误", L"温馨提示", MB_OK|MB_ICONSTOP);
SetDlgItemText(IDC_PASWRD, _T(""));
CWnd* pWnd = GetDlgItem(IDC_PASWRD);
//获取密码控件指针,设置输入焦点
pWnd->SetFocus();
}
return;
}
4、完善退出机制,当点击取消时,我们不仅要关闭登录界面,还要让整个程序退出。
void CLoginDlg::OnBnClickedCancle()
{
// TODO: 在此添加控件通知处理程序代码
// TODO: 在此添加专用代码和/或调用基类
CDialogEx::OnCancel();
//CWnd* pMain = NULL;
//pMain=AfxGetMainWnd();
//if (pMain)
//{
// MessageBox(_T("TC"));
// AfxGetMainWnd()->PostMessage(WM_CLOSE); //并且直接退出程序
//
//}
PostMessage(WM_QUIT, 0, 0);//最常用
}
- 备注:因为我们计划在CMainFrame的create()中初始化该登录对话框,此时的mainFrameWnd其实并没有完成完全创建,因为没有执行最后的return 0。所以,当我们使用AfxGetMainWnd()->PostMessage(WM_CLOSE);试图关闭框架窗口时,会有报错,追踪变量发现此时的pMain为NULL. (如下图)。所以我们使用PostMessage(WM_QUIT, 0, 0);将程序关闭
5、启用用户登录界面。在CMainFrame的Create()中,欢迎界面之后,启动模态的登录界面。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
CSplashWnd wndSplash; //创建启动窗口类的实例
wndSplash.Create(IDB_LAUNCH);
wndSplash.CenterWindow();
wndSplash.UpdateWindow(); //send WM_PAINT
Sleep(3000); //让主线程暂停3秒
wndSplash.DestroyWindow();//销毁初始画面窗口
CLoginDlg lgin; //启动用户登录界面
lgin.DoModal();if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
... ...//省略中间原来代码
retrun 0
}
最后效果视频:https://live.csdn.net/v/296547
Demo源码下载地址:(21条消息) (源码)VC/MFC在VS2017下如何实现软件启动时的欢迎画面和用户登录画面资源-CSDN文库