vs2019中C#用FindWindowEx获取记事本的文本编辑处的句柄时报错?

1.在注册窗口类时,指定了消息处理函数WndProc()。

3.在WndProc()里,对各个消息进行处理!!

  • 消息队列是线程所有,并非窗口所有和进程所有。
  • 一个线程的所有窗口,比如父窗口(主窗口)、对话框、消息框等都是使用这个线程的同一个消息队列!!!!
  • 窗口有消息循环。窗口里的控件应该就没有消息循环了吧。

而且当前响应函数会停止在MessageBox上,直到MessageBox返回才继续执行后面的语句!

说明MessageBox阻塞了函数,却没有阻塞消息分发。

用ABOUT对话框代替MessageBox,情况也是一样!ABOUT对话框出现时,父窗口(即主程序)点不出来,但父窗口WM_PAINT能正常运行!!!

即像别的文章说的,对话框和消息框会有自己的消息循环,但线程是同一个线程,所以线程的所有消息会被分发处理。

如果"OK"消息框关闭了,则不会出现"返回"消息框,再点OnButton4,仍是出现"ERROR"消息框!!!!!!!

一定要"ERROR"消息框和"OK"消息框都关闭了,才会出现"返回"消息框,再点OnButton4,才会出现"OK"消息框!!

父窗消息循环,调用消息响应函数生成了第一个消息框,同时父窗调用的消息响应函数阻塞,父窗消息循环阻塞;第一个消息框开始接手负责消息循环(是自己有消息循环还是把父窗的消息循环重入了继续使用?)。

第一个消息框消息循环,调用消息响应函数生成了第二个消息框,同时第一个消息框调用的消息响应函数阻塞,第一个消息框消息循环阻塞;第二个消息框开始接手负责消息循环(是自己有消息循环还是把父窗的消息循环重入了继续使用?)。

第二个消息框消息循环。。。

即:父窗阻塞->第一个消息框阻塞->第二个消息框

如果第一个消息框关闭,但第二个消息框未关闭,则第一个消息框调用的消息响应函数仍在阻塞中,故父窗调用的消息响应函数也在阻塞中,所以继续运行不下去,而第二个消息框仍在进行消息循环。只有第二个消息框关闭了,第一个消息框调用的消息响应函数才会继续运行并返回,然后父窗调用的消息响应函数才会继续运行并返回!!!

第二个消息框消息循环,收到父窗WM_PAINT,调用父窗消息响应函数,WM_PAINT这一部分如果没有阻塞,则消息响应函数可以马上返回。再进行下一个消息处理。所以父窗不会因为没有刷新而失去显示,否则就显示不正常了。

消息响应函数可以同时多次进入,比如父窗调用了阻塞了,第一个消息框又调用了阻塞了,第二个消息框又调用了。。。

三、试验子窗口是自己有消息循环还是把父窗的消息循环重入了继续使用?

对话框、消息框等子窗口是用自已默认的消息循环,而不是重入到父窗的消息循环!!

主窗阻塞了,第1个子窗负责消息循环,调用线程的消息响应函数(包括主窗、第1个子窗的消息响应函数);

第1个子窗阻塞了,第2个子窗负责消息循环,调用线程的消息响应函数(包括主窗、第1个子窗、第2个字窗的消息响应函数);。。。

子窗是一级一级阻塞下去的,后一个子窗关闭了,才能使前一个子窗的消息响应函数解除阻塞。

如果处在中间的子窗关闭了,它的消息响应函数仍还在阻塞中!只有它后面的子窗都关闭了,它的消息响应函数才会返回。

所以,如果是基于消息来处理事件,比如,网络SOCKET异步编程,消息处理函数中,有用到消息框MessageBox或对话框,则要小心,以免多个事件消息同时发生。因为消息框出现后,当前消息处理函数阻塞了,但消息循环仍在进行,如果有新的消息事件产生,则会运行新的消息处理函数,则有可能会产生不希望的后果。

四、后来,试验网络SOCKET异步编程,确实,弹出MessageBox后,消息循环仍在继续,如果有收到FD_READ、FD_ACCEPT等,都会执行消息处理函数。

如果消息处理函数中弹出MessageBox,这时下一个消息来了,则会再运行一个新的消息处理函数!而不是阻塞。即消息处理函数同时被多次调用,多个并存!

===================================

===================================

windows消息处理机制是这样的:

首先系统(也就是windows)把来自硬件(鼠标,键盘等消息)和来自应用程序的消息 放到一个系统消息队列中去。

而应用程序需要有自己的消息队列,也就是线程消息队列,每一个线程有自己的消息队列,对于多线程的应用程序就有和线程数目相等的线程消息队列。

其实问题的关键在于:DispatchMessage到底干了什么?

如果只是去调用相应的窗口,那自己写个switch不就可以了 ?

因为这样windows就可以知道你的程序运行到什么情况了, windows来调用你的窗口,这样你的窗口返回的时候,windows就知道你已经处理过一个消息了,如果没有新的消息进入消息队列,windows就不再会给你的进程分配时间片。

如果是你自己写switch的话,windows就不可能这样灵活的分配时间,资源利用率就会降低。

那么还要消息循环干什么,windows直接把消息发给窗口不就可以了吗?

因为你要在消息循环里把KEY_DOWN和KEY_UP组合成WM_CHAR,还可以直接屏蔽掉许多对你来说无用的消息,加快速度。

前面已经介绍从系统队列里获取一条消息,然后经过快捷键的函数检查,又通过字符消息函数的转换,最后要做的事情就是调用DispatchMessage函数,它的意思就是说要把这条消息发送到窗口里的消息处理函数WindowProc。

===================================

消息的循环过程大致为(关于消息的具体情况不再说明)

 1. 消息循环调用GetMessage()从消息队列中查找消息进行处理,如果消息队列为空,程序将停止执行并等待(程序阻塞)。

 2. 事件发生时导致一个消息加入到消息队列(例如系统注册了一个鼠标点击事件),GetMessage()将返回一个正值,这表明有消息需要被处理,并且消息已经填充到传入的MSG参数中;当传入WM_QUIT消息时返回0;如果返回值为负表明发生了错误。

    3. 取出消息(在Msg变量中)并将其传递给TranslateMessage()函数,这个函数做一些额外的处理:将虚拟键值信息转换为字符信息。这一步实际上是可选的,但有些地方需要用到这一步。

    4. 上面的步骤执行完后,将消息传递给DispatchMessage()函数。DispatchMessage()函数将消息分发到消息的目标窗口,并且查找目标窗口过程函数,给窗口过程函数传递窗口句柄、消息、wParam、lParam等参数然后调用该函数。

   5. 在窗口过程函数中,检查消息和其他参数,你可以用它来实现你想要的操作。如果不想处理某些特殊的消息,你应该总是调用DefWindowProc()函数,系统将按按默认的方式处理这些消息(通常认为是不做任何操作)。

   6. 一旦一个消息处理完成,窗口过程函数返回,DispatchMessage()函数返回,继续循环处理下一个消息。

================================

用::DiapatchMessage派送消息,在窗口处理过程(WinProc,窗口函数)返回之前,他是阻塞的,不会立即返回,也就是消息循环此时不能再从消息队列中读取消息,直到::DispatchMessage返回。如果你在窗口函数中执行一个死循环操作,就算你用   PostQuitMessage函数退出,程序也会down掉。

    所以,当窗口函数处理没有返回的时候,消息循环是不会从消息队列中读取消息的。这也是为什么在模式对话框中要自己用无限循环来继续消息循环,因为这个无限循环阻塞了原来的消息循环,所以,在这个无限循环中要用GetMessage,PeekMessage,DispatchMessage来从消息队列中读取消息并派送消息了。要不然程序就不会响应了,这不是我们所希望的。

模式对话框是卡住了啊,只不过它内部死循环中又有PeekMessage,GetMessage什么的了,所以不会对界面操作产生影响

我记得IsDialogMessage只适用于模式对话框吧,非模式对话框不需要的。

还有,如果是模式对话框,下面的窗口还是可以处理WM_PAINT的,你移动上面的模式对话框,下面的窗口可以自己重画

刚才试了一下,DispatchMessage果然是会卡住等待WndProc返回才返回的。模式对话框的确是有内嵌消息循环的,包括MessagaBox也是一样。

WM_PAINT和WM_TIMER都是优先级不同的,WM_TIMER优先级最低,只有队列里没有其他消息才会执行,WM_PAINT则较高

CreateWindowEx,这个会向窗口例程直接投递WM_CREATE,而不进入消息队列。其他消息则是比较正常的经过消息队列,然后通过GetMessage和DispatchMessage取消息和分发到相应例程,直到取到WM_QUITE就结束消息循环。

对于按键和鼠标消息则是先进入系统消息队列,然后系统队列会分发到相应的线程消息队列。

记住,消息队列是线程所有,并非窗口所有和进程所有,当然,系统队列例外。

4.定义消息结构体,开始消息循环,如:

5.编写窗口过程函数,如:

我的问题是, 当发生了一个消息时, 会执行switch 语句 中的某条case语句, 就是在此时此刻,while语句还在监听消息吗??????    

如何你在窗口函数case不返回的话这个窗口就会没响应的,你可以试试看在一个case里写Sleep(5000)

有些人已经说对了,GetMessage只负责从消息队列里面取出一条消息,TranslateMessage将键盘敲键的消息转换成WM_CHAR消息,DispatchMessage就负责调用你的窗口函数,其实相当于

处理消息的时候如果又有其他消息过来是没关系的,Windows的GetMessage是从消息“队列”里面去消息的,没来得处理的消息是会排队在消息队列里面的,微软说了Windows的消息队列足够长,一般不会出现消息丢失的情况,具体没说多长,可能根据操作系统版本不同有不同的长度限制。

另外GetMessage还有个特性,如果程序的消息队列是空的,也就是没有消息了,那么GetMessage就不会返回,直到等到下一条消息来再返回,Windows会将处于等待的程序转入Idle模式,所以那个while循环是不会出现CPU100%的占用率的。

如果你希望在程序没有消息的时候在后台做点什么事情,那么就可以利用PeekMessage,典型的MFC就是利用了PeekMessage来运作消息循环的,PeekMessage在队列中有消息的时候则把消息取回,没消息的时候也会立刻返回,这样你就可以在没消息的时候做点别的事情。

MFC的CWinApp类在Run这个函数中包含了消息循环,在没有消息的时候,Run会去调用CWinApp::OnIdle,默认的OnIdle会负责释放不需要再使用的动态连接库文件。

windows在处理消息时,会使用一个队列来存放所有消息,即消息队列。在执行case语句时,虽然窗口没有关心消息队列,但是如果此时又来了一个消息,windows会自动将该消息放入队列之中,保证消息不会丢失。当case语句处理完毕,窗口再一次运行到GetMessage时,会查看队列中有没有未处理的消息存在,通过这种方式获取之前发生但还没有处理的消息,因此不会出现对消息视而不见的情况

windows采用消息队列来处理消息,没侦听到一个事件,系统会将此消息加到消息队列,再按顺序或者按权重来处理消息。

GetMessage函数不是用来监听的,是用来获取当前线程消息队列当中的消息的,其中的第二个参数如果传递一个窗口句柄,那么就会获取该窗口相关的消息,如果传NULL,那么会将线程消息队列中所有的消息都取出来。如果创建了多个窗口,而只对其中一个窗口句柄调用GetMessage形成消息循环,那么别的窗口都会毫无响应。

GetMessage在消息列队中没有消息时是阻塞的,也就是没有消息的情况下他会通知系统把时间片交给其他进程或线程

====================================

2:当接收到WM_CREATE消息时,他的附加参数中有没有 窗口的实例句柄 在那个参数中或者 有没有其他办法在消息处理中获得窗口的实例句柄 hInstance

3;如果将WM_CREATE交给系统处理的话。。系统做了什么

重复的说下过程吧,首先是定义一个窗口类,然后注册窗口类,然后依照你前边定义好的窗口类来创建一个窗口。以上就是CreateWindow函数调用结束前所做的事情,然后会调用ShowWindow将这个创建好的窗口显示出来。

接下来遇到消息循环了,程序开始从消息队列中取消息。

首先遇到的消息就是WM_CREATE(正如你所问到的),这条消息是由系统向你的应用程序投递的。然后系统会调用你写的那个“回调函数”,它依照你写的WM_CREATE内容来创建一些控件或子窗体。(注意在这个消息中并不创建主窗口,因为创建主窗口的工作早在ShowWindow前就创建好了) 在创建都完成以后就会把整个窗口的样子绘制出来,然后程序就可以处理别的消息啦。

至于第二个问题,它是得到不应用程序的实例句柄的。它的两个赋加参数中,wParam不会被使用,而lParam则是一个指向 CREATESTRUCT 结构体的指针,用于创建子窗体(控件)的一些必要信息。

你要想得到实例句柄要调用函数,最典型的就是GetWindowLong函数。利用该函数取应用程序实例句柄的调和方式如下:

其参数有两个,第一个参数是主窗口的句柄,第二个参数是一个标记,代表你要取实例句柄,该函数还有别的功能,楼主可以自行查阅MSDN

还有其它的函数可以得到实例句柄,比如GetModuleHandle(NULL)的返回值也是实例句柄。

第三个问题已经在前边讲过了,注意你问的不对,这个消息本来就是由系统处理的,并不是你的程序处理的。

}

使用vs2105新建一个mfc ActiveX工程,工程名称为ocx_test,如果要在ocx控件中使用对话框,那么就勾选“在插入对象对话框中可用”
更改工程的属性,mfc的使用改为在静态库中使用mfc,字符集未未设置。

在工程的资源视图中插入一个对话框
为该对话框创建一个类,名称为CDialog1

在public中添加对话框的变量定义


接着在onDraw函数改为如下代码:



接下来生成工程,ocx会自动进行注册。

然后使用ie浏览器打开这个html,就可以看到网页中出现了含有对话框的ocx控件。


当使用上面创建的这种ocx,在浏览器中会有不安全提示
解决办法是在ocx_testCtrl.h文件中添加一个头文件
在该类的protect的中添加消息声明:


 

 
 
 
 
 
 
 
 
 
 
 


然后重新生成项目,再次在网页中调用,就可以看到没有出现不安全警告了。

}

我要回帖

更多关于 2019日历记事本模板免费下载 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信