怎么在MFC对话框中实现模拟键盘输入

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么在MFC对话框中实现模拟键盘输入相关的知识,希望对你有一定的参考价值。

  通常窗口中模拟输入是用SendMessage发送KEYDOWN和KEYUP消息。不过对话框中主要是控件模式,通常设置控件内容即可,没必要发送消息。 参考技术A keybd_event( )

怎么在基于对话框的MFC程序中实现多线程?

怎么设计基于对话框的多线程程序?比如,基于对话框的MFC程序可以通过按钮来调用函数,现在我想直接开多线程来处理一些数据,并且不影响原有按钮的触发功能,怎么实现?记时器和多线程试例最好,望高手前辈指点!

基于MFC的对话框程序加启动进度条(转)
对于比较大的程序,在启动的时候都会显示一个画面,以告诉用户程序正在加载,或者显示一些关于软件的信息,如Visual C++,Word, PhotoShop等。
这些启动画面在Visual C++中怎么实现呢?对于文档/视图结构的程序,可以直接使用VC提供的SplashWnd组件。可是在基于对话框的程序却不能使用SplashWnd组件。因此只能自己来实现此功能。
因为显示启动画面的同时还要进行程序的加载工作,所以要用到多线程。MFC区分了两种不同类型的多线程:用户界面(UI)线程和工作者线程。两者的区别是UI线程有消息循环,而工作者线程没有,UI线程能够创建窗口并处理发送给窗口的消息。工作者线程用来执行后台任务,这些后台任务不直接接受用户输入,因此不需要窗口和消息循环。 因为这里要显示一个画面,所以要使用UI线程。

下面结合我做的一个小软件“实用闹钟”来说明如何为对话框程序制作启动画面。
打开Visual C++建立一个对话框工程Page.
首先准备一副位图资源插入到工程中,作为启动时显示的画面。再插入一个对话框,设置ID为IDD_SPLASH。在上面放一个picture控件,类型设为”Bitmap”,图象选择刚才插入的位图。
设置对话框的Style为Popup,Border 为None,去掉Title Bar属性,并调整对话框的大小与位图等大,这样对话框显示的时候,你看到的只是图片。打开 ClassWizard为此对话框建立一个新类CSplashDlg, 基类为CDialog.
UI线程是由一个动态可创建的类来控制,该类是从CWinThread派生的,非常类似从CWinApp派生的一个应用程序类.打开ClassWizard建立一个由CWinThread派生的类----CSplashThread,在SplashThread.h 中加入 #include"SplashDlg.h",并添加一个protected型指针变量:
CSplashDlg* m_pSplashDlg; //声明一个对话框指针

下面我们将在UI线程的InitInstance()函数中调用刚才创建的对话框并显示。
BOOL CSplashThread::InitInstance()

::AttachThreadInput(m_nThreadID, AfxGetApp()->m_nThreadID, TRUE );
//:通常系统内的每个线程都有自己的输入队列。本函数允许线程和进程共享输入队列。连接了线程后,输入焦点、窗口激活、鼠标捕获、键盘状态以及输入队列状态都会进入共享状态 . (这个函数可以不用)
m_pSplashDlg=new CSplashDlg;
m_pSplashDlg->SetEnable(true);
m_pSplashDlg->Create(IDD_SPLASH);
m_pSplashDlg->ShowWindow(SW_SHOW);
return true;


为CSplashThread类添加一个函数HideSplash(), 用来隐藏启动画面(即关闭对话框)
void CSplashThread::HideSplash()

m_pSplashDlg->SendMessage(WM_CLOSE);


在ExitInstance()中释放资源:
int CSplashThread::ExitInstance()

m_pSplashDlg->DestroyWindow();
delete m_pSplashDlg;
return CWinThread::ExitInstance();


在应用程序类CPageApp中包含头文件: #include “SplashThread.h”
并添加两个变量:
public: //设为pulic类型,是为了在其他类中能够访问
CSplashThread* pSplashThread;
CSplashDlg* m_pSplashDlg;

在InitInstance()中启动UI线程:
pSplashThread = (CSplashThread*) AfxBeginThread(
RUNTIME_CLASS(CSplashThread),
THREAD_PRIORITY_NORMAL,
0, CREATE_SUSPENDED);
ASSERT(pSplashThread->IsKindOf(RUNTIME_CLASS(CSplashThread)));
pSplashThread->ResumeThread();
Sleep(1);

为了让程序一起动就显示启动画面,这段代码应该放在InitInstance()最开头的地方.
启动画面是显示了,可是结束代码应该放在什么地方呢?如果放在InitInstance()的CPageDlg dlg; m_pMainWnd = &dlg; 后面,即在构造了主对话框之后隐藏启动画面, 程序运行时会发现,启动画面结束后,还要等一会才能显示出主对话框,这样就达不到启动画面应有的效果. 最好应该在即将显示主对话框的时候隐藏启动画面. 我的这个软件中在主对话框中定义了5个子对话框类的对象,分别是page1,page2,…page5.
程序启动时的流程如下:
Page1构造 --->Page2构造 --->Page3构造---> Page4构造---> Page5构造---> 主对话框构造 --->主对话框初始化---> Page1初始化---> Page2初始化 --->Page3初始化 Page4初始化---> Page5初始化
由此可见,启动画面结束的最好地方应该是在 page5的初始化函数中
BOOL CPage5::OnInitDialog()

CDialog::OnInitDialog();
if ( ((CPageApp*)AfxGetApp())->pSplashThread != NULL)
((CPageApp*)AfxGetApp())->pSplashThread->HideSplash();
return TRUE;

到此,一个对话框程序的启动画面就这样完成了.由于是用对话框作为启动画面,所以你可以你可以发挥你的想象力,在对话框上设计出丰富多才的效果来,比如加上Flash,Gif动画等.
参考技术A 在将要处理数据的地方,使用 AfxBeginThread开创一个线程,AfxBeginThread很简单是MFC封闭的全局函数,你可以查一下用法,注意过程函数必须是静态的或是全局的。然后将数据通过AfxBeginThread的参数传递给过程函数去处理。至于计算后的结果吗。建议,你使用向主窗口发MSG的方法通知给主窗口。 参考技术B MFC线程创建函数:AfxBeginThreadWin32线程创建函数:CreateThreadCRT线程创建函数:_beginthread / _beginthreadex 这3种方法都可以 参考技术C 写一个线程函数,参数与返回值如下所示
UINT ThreadTest(LPVOID pParam);
然后在按钮里直接用如下函数启动线程
AfxBeginThread(ThreadTest,NULL);

以上是关于怎么在MFC对话框中实现模拟键盘输入的主要内容,如果未能解决你的问题,请参考以下文章

Android中怎么实现模拟键盘输入?

用js怎么写一个回车键盘事件

猎豹MFC--模拟键盘消息keybd_event mouse_event

Postmessage模拟键盘

VueTouchKeyboard——一个模拟键盘

IOS 键盘 禁止输入字母