能力值:
( LV6,RANK:90 )
|
-
-
5 楼
谢谢楼上各位,楼上的朋友给的网址里面的代码,我在网上找到了c++版本,下面是我修改后的代码,附件中是VC9项目,我的代码雪花飘过时会有闪屏现象,为什么不能实现无闪重绘呢:
#include<windows.h>
#include<time.h>
#include<stdlib.h>
const int SnowNumber=20; //雪点数量
struct SnowNode
{
POINT postion; //雪点位置
int iColor; //先前的颜色
int iSpeed; //下落速度
int iMove; //下落距离
int iStick; //粘贴度
};
SnowNode SnowNodes[SnowNumber]; //雪点数组
int hTimer=0;
int CrWind=0;
int CrStep=0; //当前循环步数(用于限速)
int ScreenWidth=0; //屏幕宽度
int ScreenHeight=0; //屏幕高度
void GetScreenSize();
void CALLBACK TimerProc(HANDLE hWnd,UINT uMsg,UINT idEvent,DWORD dwTime);
void InitSnowNodes();
void MoveSnowNodes();
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
MSG msg; //标准windows消息
LARGE_INTEGER Frequency; //高性能定时器频率
LARGE_INTEGER StartCt,EndCt;//高性能定时器计数
int ElapsedTime; //时间间隔
srand((unsigned)time(NULL));
GetScreenSize();
InitSnowNodes();
QueryPerformanceFrequency(&Frequency);
hTimer=SetTimer(0,0,rand()%5*500,(TIMERPROC)TimerProc);
if(hTimer==0)
{
MessageBox(0,TEXT("创建定时器失败"),TEXT("提示"),MB_OK|MB_ICONINFORMATION);
return -1;
}
RegisterHotKey(0,0,MOD_CONTROL,(int)'L');
while(1)
{
QueryPerformanceCounter(&StartCt); //执行运算前计数值
if(PeekMessage(&msg,0,0,0,1))
{
switch(msg.message)
{
case WM_TIMER:
TimerProc(0,0,0,0);
break; //预设风向改变时间已到
case WM_HOTKEY:
KillTimer(0,hTimer);//删除随机风向定时 器
UnregisterHotKey(0,0);//删除退出热键
InvalidateRect(0,NULL,true);
exit(1);
break;
case WM_DISPLAYCHANGE:
GetScreenSize(); //重新取屏幕的尺寸
InitSnowNodes(); //初始化雪点的数组
break;
}
}
MoveSnowNodes();
QueryPerformanceCounter(&EndCt);//执行运算后的计数值
ElapsedTime=(EndCt.QuadPart-StartCt.QuadPart)/Frequency.QuadPart;
if((ElapsedTime<0.0005))
Sleep(200); //简单限速
else if(ElapsedTime<0.0010)
Sleep(100);
else if(ElapsedTime<0.0015)
Sleep(300);
}
MessageBox(0,TEXT("消息"),TEXT("消息"),MB_OK|MB_ICONINFORMATION);
return 0;
}
void GetScreenSize()
{
ScreenWidth=GetSystemMetrics(SM_CXSCREEN);
ScreenHeight=GetSystemMetrics(SM_CYSCREEN);
return ;
}
void CALLBACK TimerProc(HANDLE hWnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
// MessageBox(0,TEXT("消息"),TEXT("消息"),MB_OK|MB_ICONINFORMATION);
srand((unsigned)time(NULL));
if(hTimer==0)
{
MessageBox(0,TEXT("创建定时器失败"),TEXT("提示"),MB_OK|MB_ICONINFORMATION);
return ;
}
SetTimer(0,hTimer,((rand()%27+4)*500),(TIMERPROC)TimerProc); //// 重设下次风向改变时间
//修改风向
if(CrWind!=0)
CrWind=0;
else
CrWind=rand()%3-1;
return ;
}
void InitSnowNodes()
{
HDC hScreenDC=0;
int j=0;
hScreenDC=CreateDC("DISPLAY",NULL,NULL,NULL);
if(hScreenDC==NULL)
{
MessageBox(0,"获取屏幕DC失败!","信息",MB_OK|MB_ICONERROR);
return ;
}
srand((unsigned)time(NULL));
for(j=0;j<SnowNumber;j++)
{
SnowNodes[j].postion.x=rand()%ScreenWidth;
SnowNodes[j].postion.y=rand()%ScreenHeight;
SnowNodes[j].iColor=GetPixel(hScreenDC,SnowNodes[j].postion.x,SnowNodes[j].postion.y);
SnowNodes[j].iSpeed=(rand()%5+1); //每次下落距离(1-5)
SnowNodes[j].iStick=(30-rand()%SnowNodes[j].iSpeed); //粘贴度(几次循环作一次粘贴连判断
}
DeleteDC(hScreenDC);
}
void MoveSnowNodes()
{
HDC hScreenDC=0;
srand((unsigned)time(NULL));
int x=0,y=0,i=0;
hScreenDC= GetDC(NULL);
if(hScreenDC==NULL)
{
MessageBox(0,"获取屏幕DC失败!","信息",MB_OK|MB_ICONERROR);
return ;
}
HPEN hNewPen = CreatePen(PS_SOLID,1,0xFFFFFF);
HPEN hOldPen = (HPEN)SelectObject(hScreenDC, hNewPen);
for(i=0;i<SnowNumber;i++)
{
x = SnowNodes[i].postion.x;
y = SnowNodes[i].postion.y;
RECT rc;
rc.left =x;
rc.top=y;
rc.right = x+15;
rc.bottom = y+15;
//InvalidateRect(NULL,&rc,FALSE);
SelectObject(hScreenDC,GetStockObject(NULL_BRUSH));
//SetROP2(hScreenDC, R2_XORPEN );
//FillRect(hScreenDC,&rc,(HBRUSH)GetStockObject(NULL_BRUSH));
//Rectangle (hScreenDC, x, y, x+15, y+15);
//SetROP2(hScreenDC,R2_BLACK);
HWND ChWnd = GetDesktopWindow(); ;//取得桌面子句柄
SetCapture(ChWnd);//
RedrawWindow(ChWnd,&rc,NULL,0x85);
SnowNodes[i].postion.x = (SnowNodes[i].postion.x+10)%1280;
SnowNodes[i].postion.y = (SnowNodes[i].postion.y + 10)%1000;
x = SnowNodes[i].postion.x;
y = SnowNodes[i].postion.y;
MoveToEx(hScreenDC, x + 7, y, 0);
LineTo(hScreenDC, x + 7, y + 15);
MoveToEx(hScreenDC, x, y + 7, 0);
LineTo(hScreenDC, x + 15, y + 7);
MoveToEx(hScreenDC, x + 2, y + 2, 0);
LineTo(hScreenDC,x + 13, y + 13);
MoveToEx(hScreenDC, x + 2, y + 12, 0);
LineTo(hScreenDC, x + 13, y + 1);
MoveToEx(hScreenDC, x + 6, y + 2, 0);
LineTo(hScreenDC, x + 9, y + 2);
MoveToEx(hScreenDC, x + 6,y + 12, 0);
LineTo(hScreenDC, x + 9, y + 12);
MoveToEx(hScreenDC, x + 2, y + 6, 0);
LineTo(hScreenDC, x + 2, y + 9);
MoveToEx(hScreenDC,x + 12, y + 6, 0);
LineTo(hScreenDC, x + 12, y + 9);
}
SelectObject(hScreenDC, hOldPen);
DeleteDC(hScreenDC);
}
|
能力值:
( LV9,RANK:780 )
|
-
-
20 楼
关于透明贴图,我用易语言实现过,也是GDI,关键代码:
.版本 2
' 下面程序画板开始
GpInput.GdiplusVersion = 1
GdiplusStartup (Token, GpInput, 0) ' 启动 GDI+
HDC = GetDC (0) ' 取屏幕DC
' 创建第1个BMP
DC1 = CreateCompatibleDC (HDC) ' 取屏幕兼容DC,目标DC
BMP1 = CreateCompatibleBitmap (HDC, 取屏幕宽度 (), 取屏幕高度 ()) ' 取屏幕兼容BMP
SelectObject (DC1, BMP1) ' 关联到目标DC
' 创建第2个BMP
DC2 = CreateCompatibleDC (HDC) ' 取屏幕兼容DC
BMP2 = CreateCompatibleBitmap (HDC, 取屏幕宽度 (), 取屏幕高度 ()) ' 取屏幕兼容BMP
SelectObject (DC2, BMP2) ' 关联到目标DC
ReleaseDC (0, HDC) ' 删除屏幕DC
' 在源BMP上画图形
you code
....
' 进行透明叠加,结果在目标DC(DC1)
tmp = 取空白字节集 (4)
tmp [3] = 透明度
bf = 取字节集数据 (tmp, #整数型, 1) ' 取tmp从位置1开始的4字节
AlphaBlend (DC1, 0, 0, 取屏幕宽度 (), 取屏幕高度 (), DC2, 0, 0, 取屏幕宽度 (), 取屏幕高度 (), bf)
|