Reputation: 229
I am trying to make a program currently that outputs a polygon to the desktop for a simple animation. The problem I am currently running into is that the animation gets an "onion" effect because the desktop isn't refreshing. I have searched for a method to refresh the desktop however because it's an animation, none of the solutions can refresh it fast enough. Below is an example of my code:
#include <iostream>
#include <Windows.h>
#include <math.h>
#include <Shlobj.h>
int main() {
//start ambrose
POINT amby[5];
POINT pos;
/* hide console window */
ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
/* Calling GetDC with argument 0 retrieves the desktop's DC */
HDC hDC_Desktop = GetDC(0);
//This is just an example of what I am doing
for (int i = 0; i < 10000; i++) {
pos.x = 600+sin(double(i)/50)*200;
pos.y = 500+cos(double(i)/50)*200;
amby[0].x = -10+pos.x;
amby[0].y = -10+pos.y;
amby[1].x = -50+pos.x;
amby[1].y = -50+pos.y;
amby[2].x = 50+pos.x;
amby[2].y = -50+pos.y;
Polygon(hDC_Desktop,amby, 3);
Sleep(10);
}
//The method I was trying before that didn't work VVVVV
//LPITEMIDLIST pidl;
//SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOP,&pidl);
//SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_IDLIST,pidl,0);
return 0;
}
Thanks
I have tried using invalidateRect as such:
...
for (int i = 0; i < 10000; i++) {
pos.x = 600+sin(double(i)/50)*200;
pos.y = 500+cos(double(i)/50)*200;
amby[0].x = -10+pos.x;
amby[0].y = -10+pos.y;
amby[1].x = -50+pos.x;
amby[1].y = -50+pos.y;
amby[2].x = 50+pos.x;
amby[2].y = -50+pos.y;
Polygon(hDC_Desktop,amby, 3);
InvalidateRect(GetDesktopWindow(),NULL, true);
Sleep(10);
}
...
I am wondering if there is anyway to call WM_ERASEBKGND or WM_DISPLAYCHANGE to force a change. Does anyone know if there is a way to call these?
Upvotes: 0
Views: 1623
Reputation: 179779
There's an easy solution, and that's to not actually draw on the desktop. Instead, create a transparent full-screen window. Since it's transparent, any pixel that you don't draw will show the desktop underneath. Hence, only your polygon pixels will hide the underlying desktop.
As a result, the desktop window never needs to be invalidated or repainted etc.
Upvotes: 1
Reputation: 804
I am not sure what you are trying to achieve. Let me just answer to problem of onion effect. A quick and dirty solution to erase what was drawn in the previous iteration could be to draw using XOR mode but the solution has a few downsides, like flicker and color could be arbitrary. A proper solution that would address both the downsides would be to do all the drawing in a memory DC and BitBlt the same to the screen.
Code for the quick and dirty solution would be -
SetROP2(hDC_Desktop,R2_XORPEN);
//This is just an example of what I am doing
for (int i = 0; i < 100; i++)
{
if(i!=0)
{
pos.x = 600+sin(double(i-1)/50)*200;
pos.y = 500+cos(double(i-1)/50)*200;
amby[0].x = -10+pos.x;
amby[0].y = -10+pos.y;
amby[1].x = -50+pos.x;
amby[1].y = -50+pos.y;
amby[2].x = 50+pos.x;
amby[2].y = -50+pos.y;
Polygon(hDC_Desktop,amby, 3);
}
pos.x = 600+sin(double(i)/50)*200;
pos.y = 500+cos(double(i)/50)*200;
amby[0].x = -10+pos.x;
amby[0].y = -10+pos.y;
amby[1].x = -50+pos.x;
amby[1].y = -50+pos.y;
amby[2].x = 50+pos.x;
amby[2].y = -50+pos.y;
Polygon(hDC_Desktop,amby, 3);
Sleep(10);
}
Upvotes: 2
Reputation: 3554
Why don't you use a transparent wnd.
class COverlayWnd : public CWnd
{
DECLARE_DYNAMIC(COverlayWnd)
public:
COverlayWnd();
virtual ~COverlayWnd();
protected:
afx_msg void OnPaint();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
// OverlayWnd.cpp : implementation file
//
The implementation. Just move the window if you want animations to run all over the desktop.
#include "stdafx.h"
// COverlayWnd
IMPLEMENT_DYNAMIC(COverlayWnd, CWnd)
COverlayWnd::COverlayWnd()
{
}
COverlayWnd::~COverlayWnd()
{
}
BEGIN_MESSAGE_MAP(COverlayWnd, CWnd)
ON_WM_PAINT()
ON_WM_CREATE()
END_MESSAGE_MAP()
void COverlayWnd::OnPaint()
{
CPaintDC dc(this);
CRect rect;
GetClientRect( &rect );
dc.FillSolidRect(&rect, RGB(1,1,1));
//paint other stuff that don't have RGB(1,1,1)
}
int COverlayWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
BOOL bRet = 0;
bRet = ModifyStyleEx(0,WS_EX_LAYERED|WS_EX_TRANSPARENT);
bRet = ModifyStyle(DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU,0);
bRet = ModifyStyle(WS_POPUP,0);
bRet = SetLayeredWindowAttributes(RGB(1,1,1),0,LWA_COLORKEY);
//the RGB(1,1,1) is the transparent color
ASSERT(bRet);
//this->EnableWindow(FALSE);
return 0;
}
Upvotes: 0