下面3个程序段中执行结果如何,为什么?
稍等,我吃完饭回来给你答案,肚子饿了
=====
不好意思,吃饭回来睡着了,sorry
第一个问题:
程序运行后是会挂掉的,因为fun()返回的是void类型,也就是说Str = fun();执行完了之后str仍旧是NULL,这时候如果你尝试着想没有开辟内存空间的str写入"Hello World" ,程序肯定是会挂掉的。
还有p = (char *)molloc(100); 这个应该是malloc,要细心喔。
第二个问题:
printf (str);这个打印出的是指针 str的地址,如果要打内容,要写成*str,写成*str,那么打出来的就是H,因为str指向的是"Hello world“第一个 字符
第三个问题:
printf (str);输出的是"hello world",因为当你调用fun(&str)的时候其实相当于将整个字符串的指针赋给了str, 这时候如果你打印*str,就会发现打印出的是字符串的第一个字符h
C语言我不是很懂,对printf()如何工作的也不是很了解,有错误的地方欢迎指出。
RedrawWindow跟InvalidateRect有什么区别
今天看到一段动画的程序,仿照的写了一个,C/C++ code void CLspiView::Animation(double x1, double y1, int x2, int y2, Ccardnode *node) { double dx=(x2-x1)/29; double dy=(y2-y1)/29; CClientDC cdc(this); CDC dc; dc.CreateCompatibleDC(&cdc); if(node->state==2) { dc.SelectObject(m_Cardback); } else { dc.SelectObject(m_CardBmp[node->num]); } int i=0; for(i=0; i<30; i++) { CRect Rect((int)x1, (int)y1, int(x1+71), int(y1+96)); RedrawWindow(Rect);// 立即重绘上一帧的画面区域 BitBltx(&cdc, (int)x1, (int)y1, 71, 96, &dc, 0, 0); x1+=dx; y1+=dy; Sleep(1); CRect rect2(int(x1-dx), int(y1-dy), int(x1-dx+71), int(y1-dy+96)); InvalidateRect(rect2, FALSE); } } 想不通RedrawWindow和InvalidateRect有什么区别,只知道不能替代,麻烦大神们解答下他俩到底有啥区别呢。------解决方案--------------------------------------------------------InvalidateRect是通过消息来调用OnPaintRedrawWindow除了有InvalidateRect的效果,还会立即调用一次OnPaint(不经过消息队列,类似 UpdateWindow)而这里用了循环,如果用消息(InvalidateRect)来重绘,只能等for结束后,才能响应消息进行绘图那就不能体现动画效果了------解决方案--------------------------------------------------------简单总结就是:Invalidate系列走消息队列RedrawWindow不走队列,直接生效Invalidate()是强制系统进行重画,但是不一定就马上进行重画。因为Invalidate()只是通知系统,此 时的窗口已经变为无效。强制系统调用WM_PAINT,而这个消息只是Post(寄送)就是将该消息放入消息队列。当执行到WM_PAINT消息时才会对敞口进行重绘。UpdateWindow只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT。发送即不经过消息队列,直接发送到对应窗口,因此此函数可以立即更新窗口。RedrawWindow()则是具有Invalidate()和UpdateWindow()的双特性。声明窗口的状态为无效,并立即更新窗口,立即调用WM_PAINT消息处理。------解决方案--------------------------------------------------------Invalidate:Invalidates the entire client area of CWnd. The client area is marked for painting when the next WM_PAINT message occurs. The region can also be validated before a WM_PAINT message occurs by the ValidateRect or ValidateRgn member function.==============
invalidaterect函数到底如何使用
该函数向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制。
BOOL InvalidateRect(
HWND hWnd, // handle of window with changed update region
CONST RECT *lpRect, // address of rectangle coordinates
BOOL bErase // erase-background flag
);
参数:
hWnd:要更新的客户区所在的窗体的句柄。如果为NULL,则系统将在函数返回前重新绘制所有的窗口, 然后发送WM_ERASEBKGND 和 WM_PAINT 给窗口过程处理函数。
lpRect:无效区域的矩形代表,它是一个结构体指针,存放着矩形的大小。如果为NULL,全部的窗口客户区域将被增加到更新区域中。
bErase:指出无效矩形被标记为有效后,是否重画该区域,重画时用预先定义好的画刷。当指定TRUE时需要重画。
返回值:
函数成功则返回非零值,否则返回零值。
说明:被标记为无效矩形的区域直到WM_PAINT消息被处理完之后才会消失,或者使用ValidateRect(),ValidateRgn()函数来使之有效。当应用程序的消息队列中为空时,并且窗体要更新的区域非空时,系统会发送一个WM_PAINT消息到窗体。
这两个都用于声明客户区无效,当下一个WM_PAINT消息到来时发生重画。
其中InvalidateRect(hwnd, NULL, true);重画时将擦除背景。
InvalidateRect(hwnd, NULL, false);重画时不擦除背景
需要:
Windows NT/2000/XP/Vista: 包含Windows NT 3.1以及之后版本。
Windows 95/98/Me: 包含Windows 95 以及之后版本。
Header: 声明在 Winuser.h中; 包含在Windows.h中。
Library: Use User32.lib.
关于WM_PAINT的问题
大多数Windows程序在WinMain中进入消息循环之前的初始化期间都要呼叫函数UpdateWindow。Windows利用这个机会给窗口消息处理程序发送第一个WM_PAINT消息。这个消息通知窗口消息处理程序:必须绘制显示区域。此后,窗口消息处理程序应在任何时刻都准备好处理其它WM_PAINT消息,必要的话,甚至重新绘制窗口的整个显示区域。在发生下面几种事件之一时,窗口消息处理程序会接收到一个WM_PAINT消息:
在使用者移动窗口或显示窗口时,窗口中先前被隐藏的区域重新可见。
使用者改变窗口的大小(如果窗口类别样式有着CS_HREDRAW和CS_VREDRAW位旗标的设定)。
程序使用ScrollWindow或ScrollDC函数滚动显示区域的一部分。
程序使用InvalidateRect或InvalidateRgn函数刻意产生WM_PAINT消息。
在某些情况下,显示区域的一部分被临时覆盖,Windows试图保存一个显示区域,并在以后恢复它,但这不一定能成功。在以下情况下,Windows可能发送WM_PAINT消息:
Windows擦除覆盖了部分窗口的对话框或消息框。
菜单下拉出来,然后被释放。
显示工具提示消息。
在某些情况下,Windows总是保存它所覆盖的显示区域,然后恢复它。这些情况是:
鼠标光标穿越显示区域。
图标拖过显示区域。
处理WM_PAINT消息要求程序写作者改变自己向显示器输出的思维方式。程序应该组织成可以保留绘制显示区域需要的所有信息,并且仅当「响应要求」-即Windows给窗口消息处理程序发送WM_PAINT消息时才进行绘制。如果程序在其它时间需要更新其显示区域,它可以强制Windows产生一个WM_PAINT消息。这看来似乎是在屏幕上显示内容的一种舍近求远的方法。但您的程序结构可以从中受益。
请教WM_PAINT消息什么时候被触发?
改变窗口大小,或者窗口被遮挡(去除遮挡)时,窗口自动产生WM_PAINT消息重绘有变化的区域(无效区)。
当你需要人工指定窗口重绘时,依此原理,可以指定窗口客户区的某些区域无效,让其重绘。
Invalidate指定整个客户区无效;
InvalidateRect和InvalidateRgn分别指定某个矩形或某区域无效。
这三个函数向窗口发送了WM_PAINT消息进入消息队列。当队列较长时(前面还有很多消息未处理),就不能即时刷新了。
你可以在上面三个函数后加一句UpdateWindow(),这样就可以立即刷新窗口了。
类似功能的函数还有RedrawWindow等等。请参阅MSDN
c++中 Invalidate();的问题
void Invalidate( BOOL bErase = TRUE );
该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。
和 UpdateWindow( )区别在于:UpdateWindow( )的作用是使窗口立即重绘。调用Invalidate等函数后窗口不会立即重绘,这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理。调用UpdateWindow函数可使WM_PAINT被直接发送到目标窗口,从而导致窗口立即重绘
Invalidate(false)不擦除背景,直接画
Invalidate(true)擦除背景
Invalidate()函数用法
Invalidate(false)不擦除背景,直接画
Invalidate(true)擦除背景
InvalidateRect只是增加重绘区域,在下次WM_PAINT的时候才生效
InvalidateRect函数中的参数TRUE表示系统会在你画之前用背景色将所选区域覆盖一次,默认背景色为白色,可以通过设置BRUSH来改变背景色。
Invalidate()之后:(MFC的,顺便了)
OnPaint()->OnPrepareDC()->OnDraw()
所以只是刷新在OnPaint()和OnDraw()函数中的绘图语句。其它地方没有影响。
Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),需要处理到WM_PAINT消息时才真正重绘。以为您Invalidate之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。
Invalidate只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行PAINT,所以不管Invalidate放哪里,都是最后的。
InvalidateRect(hWnd,&rect,TRUE);向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。
UpdateWindow()只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT
如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,如果客户区的任一部分无效,则UpdateWindow将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS将控制返回给程序中UpdateWindow调用之后的语句。
UpdateData()顺便说下,这个函数不是刷新界面用的。
UpdateData();参数为true时,将界面上控件绑定的变量的数据导到控件内,参数为false时,导入方向则相反。
c++ win32api中用什么函数可以擦区域背景?类似于InvalidateRect(hwnd,NULL,true),但不是全部区域
BOOL InvalidateRect(
__in HWND hWnd,
__in const RECT *lpRect,
__in BOOL bErase
);
这才是InvalidateRect的原型。你将lpRect设为NULL,所以才更新整个区域。如果你传入一个矩形区域结构的指针。那么就只会更新这块矩形区域。
还有这函数的用处是使得指定矩形区域将被redraw。
还有个功能类似的函数:
BOOL InvalidateRgn(
__in HWND hWnd,
__in HRGN hRgn,
__in BOOL bErase
);
只不过这个函数指定的不是某块矩形区域,而是某块区域。这区域有可能是圆的或其他什么形状。具体看你传入的区域结构怎么定义。当然当hRgn也为NULL时,功能就和InvalidateRect一个样了
还有我可没抄百度哦
关于invalidaterect的问题?
先回答你的第二个问题。
scrollWindow并不产生WM_PAINT消息。
程序第一次收到WM_PAINT消息是在你的WinMain函数里,第一次调用UpdateWindow的时候产生的。
接下来,当你的窗口被最小化,或者由于种种原因被遮盖,或者你调用了InvalidateRect这样的函数之后才产生WM_PAINT消息。
具体来说,当你的窗口被遮盖了,这可能是因为你去玩了全屏的3D游戏,把整个桌面都遮盖了,或者是你拿别的窗口把程序的窗口遮盖了等等。
Windows操作系统记录你的窗口的那一部分被遮盖了,叫做“无效部分”。这时候就会产生WM_PAINT消息,WM_PAINT消息的响应代码应当重绘窗口,并通过BeginPaint()和EndPaint()的调用使整个无效部分恢复为有效。
现在回答你的第一个问题。
InvalidateRect的作用就是产生WM_PAINT消息。
WM_COMMAND里面的ValidateRect的作用在于,正常来说,我们在WM_PAINT里面会有BeginPaint()和EndPaint()的调用,这会使得窗口有效。
但是有时候,我们的绘制不是通过BeginPaint()和EndPaint()产生的,这个时候我们却已经绘制了窗口了。这时候可以通过ValidateRect来使窗口有效。
(这时候就不能用BeginPaint()和EndPaint()来使窗口有效了,因为这一对函数只能在处理WM_PAINT消息的时候进行调用。
rect的大小是在WM_SIZE里面确定的。
窗口第一次绘制出来的时候会产生一次WM_SIZE消息。此后每次改变窗口时都会产生这个消息。因此在第一次收到WM_COMMAND消息之前,rect结构体的值就已经在第一次WM_SIZE消息时设置好了。
InvalidateRect( CRect *)
InvalidateRect(&Rect)和Invalidate()两个函数形式和功能差不多,但Invalidate是使得整个窗口无效,形成无效矩形,而InvalidateRect(&Rect)是
使得指定的区域无效。
如果你的OnPaint比较简单时,InvalidateRect(&Rect)和Invalidate()区别不是很大,因为相对重绘量少,所以整个重绘和局部重绘区别不是很明显。当你界面比较复杂时,重绘全部和重绘局部的量就比较明显,InvalidateRect(&Rect)明显效率高于Invalidate()。但是InvalidateRect(&Rect)需要你自己判断哪些区域是无效,而Invalidate()不需要(因为它是全部重绘)。所以当全部重绘的计算量高于判断局部无效的计算量时,更适合使用InvalidateRect(&Rect)。
多个WM_PAINT消息之间通过InvalidateRect使之失效的区域就会被累加起来,然后在一个WM_PAINT消息中一次得到更新,不仅能避免多次重复地更新同一区域,也优化了应用的更新操作。像这种通过InvalidateRect和InvalidateRgn来使窗口区域无效,依赖于系统在合适的时机发送WM_PAINT消息的机 制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送WM_PAINT消息之间是有延迟的。
vc++如何刷新VIEW窗口
1、实现模式对话框的OnOk()函数,在其中添加下面的代码就可以了:
((C***View)(AfxGetMainWnd()->GetActiveView()))->Invalidate();
其中C***View替换为你自己的View类的名字。
2、调用Invalidate()只是实现了刷新显示而已,至于如何实现图片大小的更新,仍需要其他代码(比如在View类中添加代表图片大小的成员变量,在OnDraw()中按照成员变量绘制图片,在OnOK()中更新View成员变量的值)。
VC 如何更新窗口
void Invalidate( BOOL bErase = TRUE ); 该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。
UpdateWindow( )的作用是使窗口立即重绘。调用Invalidate等函数后窗口不会立即重绘,这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理。调用UpdateWindow函数可使WM_PAINT被直接发送到目标窗口,从而导致窗口立即重绘。
UpdateData() 是MFC的窗口函数,用来刷新数据的。默认是TRUE
UpdateData(TRUE) ——刷新控件的值到对应的变量。 即:控件的值—>变量。 UpdateData(FALSE) —— 拷贝变量值到控件显示。 即:变量值—>控件显示。
例如,窗口中用 DDX_Text(pDX, IDC_EDIT1, m_usercode);
将IDC_EDIT1编辑框控件与m_usercode变量做了关联,如果修改m_usercode之后要想对应控件显示更改,则需要调用UpdateData(FALSE);反之在IDC_EDIT1的oneditchanged()中需要加入UpdateData(TRUE);
简单地说,如果Updatedata(TRUE) == 将控件的值赋值给成员变量,即从窗口编辑框中读入数据;Updatedata(FALSE) == 将成员变量的值赋值给控件,将数据从窗口显示。