|
I'm trying to draw an animation on a window with a transparent background using Windows API. The problem is that I can't delete the previous drawing from the window.
I set the following parameters:
InvalidateRect(m_hWnd, &sClientRect, TRUE);
paintParams.dwFlags = BPPF_ERASE;
paintParams.pBlendFunction = &m_sBlendfunc;
But it still doesn't work. The animation I wanted is moving the circles across the screen. What I get instead is artifacts of their motion because the window is not cleared before each draw.
See my full code below:
#include "DrawTest.h"
DrawTest* m_sDrawTest;
DrawTest::DrawTest()
{
m_pAnimation = NULL;
m_sDrawTest = NULL;
m_nFrameindex = 0;
}
DrawTest::~DrawTest(void)
{
if(m_pAnimation)
delete m_pAnimation;
m_pAnimation = NULL;
if(m_sDrawTest)
delete m_sDrawTest;
m_sDrawTest = NULL;
}
int DrawTest::Init(AnimationManager* pAnimationManager,HINSTANCE hInstance,int nCmdShow)
{
m_sDrawTest = this;
m_pAnimation = pAnimationManager->GetAnimation(2);
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndDrawTestProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = sWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
m_hInst = hInstance;
m_hWnd = CreateWindow(
sWindowClass,
sTitle,
WS_POPUP,
200, 200,
1024, 600,
NULL,
NULL,
hInstance,
NULL
);
if (!m_hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
SetWindowPos(m_hWnd,
HWND_TOPMOST,
0,
0,
0,
0,
SWP_NOSIZE | SWP_NOMOVE);
ShowWindow(m_hWnd,
nCmdShow);
UpdateWindow(m_hWnd);
return 1;
}
void DrawTest::TimeStep(){
PostMessage(m_hWnd, WM_PAINT, 0, 0);
}
LRESULT CALLBACK WndDrawTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_ERASEBKGND:
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_PAINT:
m_sDrawTest->OnNextFrame(hWnd);
SetWindowPos(hWnd,
HWND_TOPMOST,
0,
0,
0,
0,
SWP_NOSIZE | SWP_NOMOVE);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
void DrawTest::OnNextFrame(HWND hUILoopWnd)
{
if(m_nFrameindex > m_pAnimation->GetNumOfFrames() - 1)
return;
RECT sClientRect;
GetClientRect(hUILoopWnd, &sClientRect);
InvalidateRect(m_hWnd, &sClientRect, TRUE);
m_sBlendfunc.BlendOp= AC_SRC_OVER;
m_sBlendfunc.BlendFlags = 0;
m_sBlendfunc.SourceConstantAlpha = 255;
m_sBlendfunc.AlphaFormat = AC_SRC_ALPHA;
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hUILoopWnd, &ps);
GetClientRect(hUILoopWnd, &sClientRect);
BP_PAINTPARAMS paintParams = { sizeof(BP_PAINTPARAMS) };
paintParams.dwFlags = BPPF_ERASE;
paintParams.pBlendFunction = &m_sBlendfunc;
HDC hBBDC;
HPAINTBUFFER hPBuffer;
paintParams.cbSize = sizeof(paintParams);
hPBuffer = BeginBufferedPaint(hdc, &sClientRect, BPBF_COMPATIBLEBITMAP, &paintParams, &hBBDC);
Draw(hBBDC);
m_nFrameindex ++;
EndBufferedPaint(hPBuffer, TRUE);
EndPaint(hUILoopWnd, &ps);
}
void DrawTest::Draw(HDC hBBDC)
{
HDC hdcScreen = GetDC(NULL);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
bool test = false;
HGDIOBJ hbmpOld = SelectObject(hdcMem, m_pAnimation->m_pFramesArray[m_nFrameindex]->hBmp);
HBITMAP ptemp = CreateCompatibleBitmap(hdcMem,m_pAnimation->m_pFramesArray[m_nFrameindex]->nWidth,
m_pAnimation->m_pFramesArray[m_nFrameindex]->nHeight);
DeleteObject(ptemp);
test = AlphaBlend(hBBDC,m_pAnimation->m_pFramesArray[m_nFrameindex]->nPtX,m_pAnimation->m_pFramesArray[m_nFrameindex]->nPtY
,m_pAnimation->m_pFramesArray[m_nFrameindex]->nWidth, m_pAnimation->m_pFramesArray[m_nFrameindex]->nHeight,
hdcMem,0,0,m_pAnimation->m_pFramesArray[m_nFrameindex]->nWidth,m_pAnimation->m_pFramesArray[m_nFrameindex]->nHeight,m_sBlendfunc);
DWORD test10 = GetLastError();
SelectObject(hdcMem, hbmpOld);
test = DeleteDC(hdcMem);
test = ReleaseDC(NULL, hdcScreen);
}
|
|
|
|
|
i havn't looked ur code, but the first thing coming to my mind for these things is layerd windows , check it out(http://msdn.microsoft.com/en-us/library/ms997507.aspx)
If u can Dream... U can do it
|
|
|
|
|
Hi!
I'd like to use 5 different shockwave Flash objects in my MFC application. Each of the objects should have its own member variable and message notification (mouse over, left click). When I place only one object all is well: I add a variable and the member variable wizard gives a variable type of 'CShockwaveflash1' (or similar) and also creates a class with the same name.
However, if I place the 2nd shockwave object and would like to add its member variable, the variable type is grayed out and shows the same previous type, 'CShockwaveflash1'. With this way, if I create an OnMouseOver event, it fires with both objects thus making painful distinguishing which object has been mouse overed by the user.
I duplicated the 'CShockwaveflash1' class as 'CShockwaveflash2', and manually created two member variables, eg. CShockwaveflash1 m_flash1, CShockwaveflash2 m_flash2. With this way, I was able to receive the appropiate mouse events for each objects but the member variables aren't working at all: the IntelliSense won't pop up any members
For testing purposes, I deleted all the SW objects, the 'CShockwaveflash1' class also (.h and .cpp) and tried to re-place a new SW object on the form: it still gives the grayed variable type 'CShockwaveflash1' despite it has been deleted! It just stucks and the only way to get back is to start a new project. I checked the entire solution to get rid of 'CShockwaveflash1' but with no success.
It's very frustrating and there must be an easier way to handle all this. Any tip or hint would be highly appreciated.
|
|
|
|
|
I'm coding with VC++ 2008 and I've got a dialog with none border.
Now I wanna resize it in some other message handlers, such as BTN_CLICKED, than CDialog::InitDialog(), using CWnd::MoveWindow().
But it won't work.
So anyone could help?
Many thanks in advance.
|
|
|
|
|
Krauze wrote: But it won't work.
What won't work? Unless you show the code that you are using and explain what you expect to happen and what actually happens, we cannot begin to guess what might be the problem.
Just say 'NO' to evaluated arguments for diadic functions! Ash
|
|
|
|
|
resize : you mean dynamically ? or only when the dialog is created ?
if dynamically, then, Windows User Experience Guidelines says that you need a border to be able to "grab" to something to resize the dialog, and that's only for resizing the dialog frame, not moving and repositioning the content which you will have to do manually.
If you really need to have no border for your dialog, then you need something to "anchor" the mouse position and handle the mouse movements to compute the new dialog frame size.
for example (in pseudo-code ) :
in the handler for LBUTTON_DOWN for the dialog , get and store the mouse position (A) and capture it (Get/SetCapture)
in the handler for LButtON_UP, get the current mouse position (B); compute the difference between A anb B and resize the dialog (SetWindowPos) with the computed diffference.
...
good luck with that.
Watched code never compiles.
|
|
|
|
|
I have problem when printing from a service. When I print from my service and then open my printer, there is a printing job in queue, but it is stuck there.
|
|
|
|
|
Is this a C/C++/MFC problem or a Windows problem with the printer configuration? Can you print from other applications or print the test page from Windows?
CQ de W5ALT
Walt Fair, Jr., P. E.
Comport Computing
Specializing in Technical Engineering Software
|
|
|
|
|
That is the problem of my service. I can print well from other programs. Follow this link. I think I have to log on under a user to print, I tried but failed!
|
|
|
|
|
The installed printer is a user profile property. If your service is running under SYSTEM account (see service property login), there is no printer available. You can verify this by running REGEDIT.EXE with the tool SrvAny under SYSTEM account. There is no key HKEY_CURRENT_USER\Printers for the user SYSTEM. It's the same with network drives.
Two solutions:
1. Configure your service to run under any local administrator account. So you can manually login with this account and config the printer before using it.
2. Run your service under SYSTEM account, open the explorer process and use this handle to call ImpersonateLoggedOnUser(), do printing and finally call RevertToSelf (some examples are available in MSDN). In this way the current logged on users printer (and all other settings) will be used.
Under Windows7/Vista/W2k8 interactive services are no more supported. That means you can not show any window or message box at current users desktop from within your service.
|
|
|
|
|
Thanks, I can print from my service now. But there's still a problem.
After calling ImpersonateLoggedOnUser(), I call PrintDlg() to display Print Dialog Box. And I can only print if hwndOwner of PRINTDLG structure is set to NULL. If hwndOwner is set to the Handle of parent window, there's no printer to select in the Print Dialog Box and this dialog box is the dialog box of the function PrintDlgEx(). Quite weird!
|
|
|
|
|
I assume with 'parent window' you suppose the window created by your service, that belongs to the SYSTEM context/process and may annul the previous impersonation.
Try FindWindow("Progman", "Program Manager") as owner, that's an unique valid window of logged on users desktop.
|
|
|
|
|
I am drwaing images on a view So I develped a owner draw control to darw images.
I also need to draw blue order around on mouse hover So I am also drwing. But I am facing some flickering issue How can I reduce it?
|
|
|
|
|
By making your paint code as swift as possible: don't create objects, don't paint more than necessary, etc. Show your code if you need detailed help.
Alternatively, for rubber-banding kind of stuff, have a look at ControlPaint.DrawReversibleFrame(). Warning: it also paints outside the intended Control!
|
|
|
|
|
You can try:
1. use memory dc
2. draw what is necessary
|
|
|
|
|
You might also try handling WM_ERASEBKGND. Do nothing in the handler and return a non-zero value. This will prevent the view window being flood-filled with the window class brush color just before each call to WM_PAINT.
The other key is using some double-buffering scheme. Draw your content on an off-screen bitmap and then blit that to your view, rather than drawing in the view itself.
L u n a t i c F r i n g e
|
|
|
|
|
When is the flickering occuring?
Steve
|
|
|
|
|
Flicker occurs when there are intermediate pixels on the screen. Example: draw a blue,filled rectangle, then draw a non-rectangle bitmap over that. The blue pixels 'under' the bitmap cause the effect. There are 2 solutions: 1) avoid the drawing of unneeded pixels by making your algorithm better (and faster) or using regions (see winapi documentation), 2) draw everything in a buffer (memory DC) and transfer that to the screen. This is called 'double buffering'.
The first solution is most of the times too difficult to implement, so solution 2 is widely used, although it is actually slower.
|
|
|
|
|
Hello all
Good day . Though this question is not relevant to MFC or Win32 but to do with VB generic behavior =>
I have a outlook plugin ( COM plugin ) developed in VB 6.0 . We have an external application which uses the outlook addin to get the contact details from outlook. The problem is here =>
We create a new application object and free it as below =>
Set gApp = New Outlook.Application
....
Set gApp = Nothing
After this code is executed when we click on outlook application it says "Operation failed" . It looks like the outlook application object is not well freed by the statement Set gApp = Nothing . But I checked by adding the line below to ensure if the gApp is really free or not .
If gApp is Nothing
Then Log("gApp is free")
Else
Log ( "gApp is not free")
Endif
Even after this check it shows gApp is free which does not seem to be the case .
What can I further do to make sure the object is really made NULL !!!!
Going crazy with VB
regards
redindian
|
|
|
|
|
dharani wrote: Going crazy with VB
Then please post your question in the correct forum! This has nothing to do with C/C++/MFC.
Just say 'NO' to evaluated arguments for diadic functions! Ash
|
|
|
|
|
dealing with outlook is especially difficult.
first you need to attempt to connect to running instance and if successfull set a flag.
if not current instance create one.
do your stuff.
then if you connected to running instance just free your stuff and go bye bye.
if you created an instance call close on it and then go bye bye.
NEVER call close on an instance you didnt create.
|
|
|
|
|
Roger Broomfield wrote: dealing with outlook is especially difficult.
I have not found this either in C++ or C#, the latter being especially easy.
Just say 'NO' to evaluated arguments for diadic functions! Ash
|
|
|
|
|
What I found, was that Outlook 2007, was unfriendly. It is a single instance multi process application that needs to be specifically closed. If you start it, you close it, if you dont specifically close an instance you started it sits in running processes until you log off. If you dont start it, you dont close it, but you do release all instances of objects you created. Maybe this is because I dont have the latest VS. But I dont see how that would affect the Outlook object model.
|
|
|
|
|
I use the
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
to check the memory leak, but it output a lot of non-useful info, Is there good way to check where the memory leak?
|
|
|
|
|
normally when u create project in Visual studio ,and after debugging it (ofcourse in debug mode) , when u close the app, Visual studio will shows any unfreezed memory in the output window( ALT+CTRL+ O).
sometimes this information is sufficient to detect the memory leak(depends on codes and the persons knowledge)
if u r trying to find memory leak and vs's output is not sufficient try using boundsckecer or similar softwares ( http://en.wikipedia.org/wiki/BoundsChecker) . Boundschecker is not free.
visual leak detector is a free one(http://www.codeproject.com/KB/applications/visualleakdetector.aspx)
hopes this helps.
If u can Dream... U can do it
|
|
|
|
|