|
Luc, or anybody else that knows, here is what I wrote:
<br />
LRESULT<br />
CMainWin::ReportAEvent(WPARAM wParam, LPARAM lParam)<br />
{<br />
failCount ++;<br />
RECT rect1;<br />
rect1.top = m_X;<br />
rect1.bottom = m_X + 20;<br />
rect1.left = 2;<br />
rect1.right = 20;<br />
this->InvalidateRect( &rect1 );<br />
this->UpdateWindow();<br />
return 0;<br />
}<br />
Now, my OnPaint rountine looks like the following:
<br />
afx_msg void CMainWin::OnPaint()<br />
{<br />
CPaintDC DC(this);<br />
<br />
RECT rec1;<br />
this->GetUpdateRect( &rec1 );<br />
if ( rec1.top != 0 || rec1.bottom != 0 || rec1.left != 0 || rec1.right != 0 ) {<br />
int i = 10;<br />
int j = 20;<br />
int k = i + j;<br />
}<br />
.<br />
.<br />
.<br />
Originally, I was calling Invalidate method rather than InvalidateRect and Update. When I was calling Invalidate method, the window was being updated from ReportAEvent via a call to OnPaint. Now, when I have the call to InvalidateRect and Update I am not getting a call to OnPaint from the method ReportAEvent. In addition, as far as I can tell, the body of the if statement is never executed.
This does not make a lot of sense to me. I would expect the call to UpdateWindow to be generating a WM_PAINT request and therefore a call to OnPaint. In addition, I have tried running the program where part of the window is covered by anther window and then the original window is brought to the foreground. In this case, I would expect the body of the if statement to be executed. It is not.
Please tell me what I am missing.
Thanks
Bob
|
|
|
|
|
Hi Bob,
if I understand you correctly, there are two issues:
1. the body of OnPaint is never executed
I don't know how that is possible. Is OnPaint called at all?
However I am a bit suspicious about m_X, sounds like a strange name for a vertical coordinate.
2. OnPaint is not called without UpdateWindow().
That may be normal, the WM_PAINT processing has lower priority, if your app is busy all the time
it may never paint a thing.
FYI: you might check the return value of GetUpdateRect instead of the full rect checking.
suggestion: if OnPaint is called, but your rect is wrong somehow, nothing new might be painted;
I would then experiment with a much larger rect (e.g. screen/logical coordinate confusion).
Hope this helps.
|
|
|
|
|
Luc,
Thanks for the response. You were right, m_X is the wrong name and wrong variable for
a vertical coordinate. That was a problem and I fixed it. Now, I am getting calls to OnPaint.
However, GetUpdateRect is still not returning a rectangle. I have two calls to Sleep in the
processing routine, so there is time for the GUI interface to update the window. Sleep
is called with 50, meaning 50 milliseconds. Here are my routines:
<br />
LRESULT<br />
CMainWin::ReportAFailure(WPARAM wParam, LPARAM lParam)<br />
{<br />
failCount ++;<br />
RECT rect1;<br />
rect1.top = m_Y;<br />
rect1.bottom = m_Y + 200000;<br />
rect1.left = m_X;<br />
rect1.right = m_X + 200000;<br />
this->InvalidateRect( &rect1 );<br />
this->UpdateWindow();<br />
return 0;<br />
}<br />
<br />
afx_msg void CMainWin::OnPaint()<br />
{<br />
CPaintDC DC(this);<br />
<br />
RECT rec1;<br />
int retValue = this->GetUpdateRect( &rec1 );<br />
if ( retValue != 0 || rec1.top != 0 || rec1.bottom != 0 || rec1.left != 0 || rec1.right != 0 ) {<br />
int i = 10;<br />
int j = 20;<br />
int k = i + j;<br />
}<br />
.<br />
.<br />
.<br />
The body of the if statement is never executed. The return value from GetUpdateRect is always 0. I do not understand why.
Bob
|
|
|
|
|
Hi Bob,
1.
I am not sure where you have put the Sleep stuff; if it is inside a handler (button click, paint,...)
then it won't help you, since that would cause the GUI thread to sleep, i.e. not do anything for
as long as it takes.
2.
many years ago screen coordinates were only 15 or 16 bits effectively (even when their variables could hold more); I don't know what GDI currently accepts. so a wild guess could be your big rect is invalid, InvalidateRect accepts or maybe rejects it (look at its return value!),
and somehow Windows decides there still is nothing to update due to the invalid rect parameters.
If you doubt your coordinates, just use 0 for top and left, 30000 for bottom and right.
BTW, you should always test the return values, and especially when your code does not do what you would like to get...
|
|
|
|
|
Luc,
I put the Sleep calls in the thread that did the computation, not in the GUI thread. The idea was
to give the GUI thread a chance to catch up if it was behind. I also tried setting top and left to 0
with 30000 for bottom and right as you suggested. That did not help either. The methods InvalidateRect and UpdateWindow are void so there are no return values to check.
However, I now believe I understand what the problem was. I was defining a local variable of
type CPaintDC. When the constructor for CPaintDC is called, it was clearing the invalid region. In addition, sitting bottom past the bottom of the screen results in Windows setting it to the bottom of the screen. Now, I can solve my problem of my screen flickering.
Luc, thanks for your help in this matter.
Bob
|
|
|
|
|
Hi Bob,
You're welcome; I am glad I could be of some help.
Could you please show us the relevant code now it is working, similar to what you had here.[^] Thanks.
|
|
|
|
|
Luc,
Here is my working code:
LRESULT
CMainWin::ReportASuccess(WPARAM wParam, LPARAM lParam)
{
successCount ++;
static RECT rect1;
rect1.top = 300;
rect1.bottom = 30000;
rect1.left = 0;
rect1.right = 30000;
this->InvalidateRect( &rect1, 0 );
this->UpdateWindow();
return 0;
}
LRESULT
CMainWin::ReportAFailure(WPARAM wParam, LPARAM lParam){
failCount ++;
static RECT rect1;
rect1.top = 200;
rect1.bottom = 30000;
rect1.left = 0;
rect1.right = 30000;
this->InvalidateRect( &rect1, 0 );
this->UpdateWindow();
return 0;
}
afx_msg void CMainWin::OnPaint()
{
RECT rec1;
int retValue = this->GetUpdateRect( &rec1 );
if ( rec1.top == 200 ) {
char buffer1[512];
CPaintDC DC(this);
sprintf_s( buffer1, "Failed: %d ", failCount );
DC.TextOut( m_X, 200, buffer1 );
return;
}
if ( rec1.top == 300 ) {
char buffer1[512];
CPaintDC DC(this);
sprintf_s( buffer1, "Passed: %d ", successCount );
DC.TextOut( m_X, 300, buffer1 );
return;
}
CPaintDC DC(this);
DC.TextOutW( m_X, 50, TEXT("Other Text"), 11 );
DC.TextOutW( m_X, 100, TEXT("Other Text"), 11 );
.
.
.
You will notice that I do not erase the background when I call InvalidateRect. In addition, I checked in the debugger that the routine OnPaint was taking the right path.
Bob
|
|
|
|
|
Hi Bob,
thanks for sharing the code.
I do still have some remarks:
1. IMO not erasing the background will result in artefacts, such as old text still showing
under new text.
2. you still are not using the updaterect the way it is intended:
your OnPaint should not test for boundaries being equal, it should basically consist of a
series of this pseudocode:
if (theRectThing1Affects.overlaps.with.updateRect) paint.thing1.in.theRectThing1Affects;
if (theRectThing2Affects.overlaps.with.updateRect) paint.thing2.in.theRectThing2Affects;
if (theRectThing3Affects.overlaps.with.updateRect) paint.thing3.in.theRectThing3Affects;
And of course you then should use real heights, i.e. adjust the rect1.bottom values.
The way you have it just may still cause a dirty window when an overlapping window with top==200
(or 300) gets removed.
|
|
|
|
|
Luc,
Your first point is valid, therefore, I am planning on writting some extra spaces accross the
row when I do the update. If I calls InvalidateRect with the erase option, the text appears to
blink. This is something I do not want.
On your second point, I agree with you that my OnPaint routine needs to be a little smarter. I am plan on working on these today and tommorow. I have a small test program that actually works. If you want me to, I can upload it. Just tell me where.
Bob
|
|
|
|
|
Hi Bob,
to reduce flickering, you should make the invalid rect as small as possible, so if the text
is much narrower than your window, try to give reasonable horizontal coordinates as well.
however, if your update frequency is many times per second (if your app is erasing and painting more than it is calculating something), then anything you erase will cause flickering, since erasing takes almost the same time as painting does, hence the text is disappearing and re-appearing all the time, which is always noticeable, unless...
There basically are two rather drastic remedies:
1.
reduce the screen refresh rate; one way I like to apply is perform the calculations without updating the screen; and have a timer periodically (say twice per second) update the screen,
that is sufficient to show progress, but is much less disturbing, since the time your text
is erased now is only a fraction of 1 percent, hardly noticeable. The added advantage is
your performance will be better (more calculations and fewer screen actions per second).
2.
The other approach is to use double-buffering, which basically means that the entire form (or some
part of it) is first erased and painted in memory, then that memory bitmap gets copied to the screen replacing what is there (hence no erase and minimal visual disturbance).
I cannot provide you with any details; I use it quite often in .NET, where it requires no effort
at all, however I do not know how complex it is in GDI.
And it can make sense to combine it all: invalidate only what is needed, apply double-buffering,
and lower the update frequency.
As for code, I don't need it right now; if you make significant further progress, I am still
interested to learn the details; then we can exchange email addresses and send a zip.
Regards,
|
|
|
|
|
Luc,
I have my small program working the way I like it. I would be happy to send it to you, if you
want me to.
Bob
|
|
|
|
|
I now have an easy fixed for this problem. When you are doing the update, you call
CWnd::Invalidate with an argument of 0. In this case, the 0 stands for false and
Windows will not earse the screen. In addition, the window will not flicker.
Bob
modified on Monday, December 29, 2008 3:09 PM
|
|
|
|
|
Write a program that will read a list of numbers and a desired sum,then determine subset of numbers in the list that yield that sum if such a subset exists.
|
|
|
|
|
Hi,
I have two hints for you:
1. A program quite often is just a recipe that explains to a computer how a human person (with
lots of accuracy, courage, and perseverance) would solve the given problem.
2. Recursion normally gets used to replace a single problem by one or several smaller problems.
That should be sufficient.
|
|
|
|
|
Running on Windows XP sp2, with IE7, I notice that when I use the web browser component and call Navigate() with a res url (i.e. something like res://c:\some\path\to\program\program.exe/stuff.html) that it no longer opens the embedded html resource.
Either I get a dialog (I think from IE) complaining about an unknown file type "stuff" and "Navigation to the webpage was canceled" in the browser view, or I just see "This page cannot be displayed" in the browser view. This is used to all work fine, and now it doesn't.
The rc file looks something like this:
STUFF.HTML HTML DISCARDABLE "res\\stuff.html"
The url passed to Navigate (in this example) would be "res://c:\\some\\path\\to\\program\\program.exe/stuff.html". The dialog error (in the first case) makes me think that somehow the stuff.html is getting truncated and the ".html" is getting lost. Is there some new problem with this, as I never had a problem before? I notice that if you change the URL to "res://c:\\some\\path\\to\\program\\program.exe/stuff" (i.e. drop the .html part) then it works.
¡El diablo está en mis pantalones! ¡Mire, mire!
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
SELECT * FROM User WHERE Clue > 0
0 rows returned
Save an Orange - Use the VCF!
VCF Blog
|
|
|
|
|
Just a hunch, but:
I think it may have something to do with the fact that immediately preceding the "/stuff.html" is a path element called "program.exe".
The fact that there is a dot after "program" may be confusing the parser to think that everything after the dot is the file type.
What do you think?
|
|
|
|
|
I'm not sure. According to MSDN and other docs I found, that is supposed to be the format, i.e.
res://fully-qualified-exe-filename/resource-name
¡El diablo está en mis pantalones! ¡Mire, mire!
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
SELECT * FROM User WHERE Clue > 0
0 rows returned
Save an Orange - Use the VCF!
VCF Blog
|
|
|
|
|
You're probably right.
It was just a first thought.
|
|
|
|
|
no prob. Interestingly enough I just tried this with an older version of IE and it works perfectly, so it's definitely an issue with IE7, some subsequent patch to IE7, and/or some related windows component. Joy.
¡El diablo está en mis pantalones! ¡Mire, mire!
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
SELECT * FROM User WHERE Clue > 0
0 rows returned
Save an Orange - Use the VCF!
VCF Blog
|
|
|
|
|
I looked into the htm file I once used for an HTML Dialog box in MFC.
It uses a resource graphic, and it specifies the graphic name as:
src="res://Program.exe/#2/#133"
If I recall correctly, the #2 indicates the resource TYPE, such as bitmap, and the #133 represents the exact resource identifier.
Try that type of res URL, and see if it works.
You'll have to determine the correct number for the resource type of HTML.
|
|
|
|
|
res Protocol
--------------------------------------------------------------------------------
Specifies a resource that will be obtained from a module.
Syntax
res://sFile[/sType]/sID
Tokens
sFile
Path and file name of the module that contains the resource.
sType
Optional. String or numerical resource type. This can be either a custom resource or one of the RT_ predefined resource types described in the FindResource function reference. If a numerical resource type is specified, the actual number of the identifier, not the identifier name, must follow a # character. See the example for more information. If this parameter is not specified, the default resource type is RT_HTML.
sID
String or numerical identifier of the resource. If a numerical identifier is specified, the actual number of the identifier, not the identifier itself, must follow a # character. See the example for more information.
Remarks
Available as of Microsoft Internet Explorer 4.0 or later.
Remember, URLs require that special characters such as '#' be escaped. Use '%23' to escape the '#' character.
Note Internet Explorer 6 Service Pack 1 (SP1) no longer allows browsing a local machine from the Internet zone. For instance, if an Internet site contains a link to a local file, Internet Explorer 6 SP1 displays a blank page when a user clicks on the link. Previous versions of Internet Explorer followed the link to the local file.
Example
This example shows the correct and incorrect ways to format the numerical identifier for the resource type.
#define MYBITMAP 234
// This is correct.
"res://mydll.dll/#2/#234"
// This is not correct.
"res://mydll.dll/#2/MYBITMAP"
|
|
|
|
|
Hi all.
I am trying to create a simple magnifier application which follows the mouse and magnifies the portion around the mouse cursor. I know how to get a screenshot of a desktop. I have tried GDI way and DirectX9 Surface way, but DX surface is too slow for realtime capturing. So I am staying with GDI.
The problem is - when I get a screenshot my magnifier application is included, too. I tried to GetNextWindow and GetFocus to get HDC only for the active window and then render HDC into memory DC. But it is a nightmare - some applications have multiple windows so I get only one of them and the other part of the shot is a mess (from previous shots). I guess it would be really hard to get DC for every window beneath my own and to combine all the DC images myself. Brrr...
One approach could be to hide my app, capture screen, restore my app. But it is not suitable for realtime work.
Of course, I know that Windows keeps track of window clipping regions so area behind my window would not be updated in other windows WM_PAINT. But I think I can force it to render if I use WS_EX_LAYERED style and 99% visibility for my app - then Windows invalidates area even behind my window. Of course, I can remove CAPTUREBLT flag from BitBlt when capturing and then I won't get my window because all layered windows would be ignored. But then I do not get any of the layered windows (like tooltips etc.).
I know that Vista Magnification API can do the trick but it does not work on XP
So the problem is - how can I virtually "erase" my app from the screenshot and get area behind it?
Thanks for any ideas.
modified on Friday, December 26, 2008 9:45 AM
|
|
|
|
|
Hi All
I have a problem to get GetClipboard data?I have a code which is working fine for copy data.I read all data which is copy from system.But problem is when i use Cut option then i am geting NULL Data.Plz help me
LPDATAOBJECT pDO;
TCHAR szPath12[MAX_PATH];
HRESULT hr = OleGetClipboard(&pDO);
FORMATETC fmt = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
STGMEDIUM stgm;
hr = pDO->GetData(&fmt, &stgm);
if(S_OK == hr)
{
UINT nFiles = DragQueryFile((HDROP)stgm.hGlobal, -1, NULL, 0);
int i = 0;
for( i = 0; i < nFiles; i++)
{
ij=1;
DragQueryFile((HDROP)stgm.hGlobal, i, szPath12, MAX_PATH);
szPath12;
}
ReleaseStgMedium(&stgm);
}
pDO->Release();
|
|
|
|
|
Hi
I am getting the error show below.This is the linker error and i am not able to resolve it.I am afraid that I am giving improper selection in the Properties.
Kindly help me out.
1>AltABFUtil.obj : warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/INCREMENTAL:NO' specification
1>msvcprt.lib(MSVCP80.dll) : error LNK2005: "class std::basic_string<char,struct>,class std::allocator<char> > __cdecl std::operator+<char,struct>,class std::allocator<char> >(class std::basic_string<char,struct>,class std::allocator<char> > const &,class std::basic_string<char,struct>,class std::allocator<char> > const &)" (??$?HDU?$char_traits@D@std@@V?$allocator@D@1@@std@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@ABV10@0@Z) already defined in abflib.obj
1>msvcprt.lib(MSVCP80.dll) : error LNK2005: "class std::basic_string<char,struct>,class std::allocator<char> > __cdecl std::operator+<char,struct>,class std::allocator<char> >(class std::basic_string<char,struct>,class std::allocator<char> > const &,char const *)" (??$?HDU?$char_traits@D@std@@V?$allocator@D@1@@std@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@ABV10@PBD@Z) already defined in abflib.obj
1>LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
|
|
|
|
|
You are trying to link with two different versions of the C runtime library (MSVCRT). This usually occurs because you are linking with object code or a static library that was compiled against a different variant of the CRT.
Make sure that all of your code uses the same run-time library option (it's in the C/C++ compiler properties, in the Code Generation page).
|
|
|
|
|