Introduction
The snippet is a simple class and we can use it to shake our Windows. Many IM tools have these kind of functions. When you chat with your friend, you click a button, then you and your friend's chatting dialog begins to shake. I do it using multithreading, so it's a very funny routine. Download it and have fun.
Background
When the IM tool adds the function, I always want to implement it. So, the chance is here, and I will move on with my article. I'll explain it to you, it is not very hard. Do not use any complex data structures and algorithms.
Using the Class
To use this class is as simple as eating eggs, it only needs some steps. First add the three files(JitterWndClass.h, JitterWndClass.cpp, and shake.wav) to your project. Warning! It's three, not two. For this reason, this time the class needs an external sound file "shake.wav". When an application calls its method to shake, at the same time play this sound file.
Just several steps to use the class:
#include "JitterWndClass.h"
JitterWndClass jit;
jit.Init(hWnd); jit.Shake();
Having finished its usage, let's continue to discover its principle.
About how to move a window, we all can think of the function SetWindowPos()
! The class just uses it. The function's usage is very important.
BOOL SetWindowPos( const CWnd* pWndInsertAfter,
int x, int y, int cx, int cy, UINT nFlags );
To know more about it, find it on MSDN.
We want to alter its second and third parameters just in a single thread. We start a thread to modify the position of window. And how to modify the position, we need the data. Look at this picture:
The black points on the picture are the positions we need to generate. The closer to the center, the more points there should be. Where to get the data? Sometimes, when we design an algorithm, we can create a console application first, for it is easy to input and output data. It is easy to observe. Look at the following code, it is used to generate some digits:
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
int GetSign()
{
return (rand()%2)?-1:1;
}
int main(int argc, char* argv[])
{
::srand (::GetTickCount ());
int i;
for(i=50;i>=0;i--)
{
if(i%6==0) printf("\n");
printf("%d ",GetSign()*rand()%20*i/10);
}
return 0;
}
The result is as shown in the following picture:
We can see from the picture that basically, it is randomly arranged in descending order. So, using the snippet, we generate the point and store it into a POINT array.
Generate the points' array:
BOOL JitterWndClass::Init(HWND hWnd)
{
::srand (::GetTickCount ());
if(pt) free(pt);
pt=(POINT *)malloc(sizeof(POINT)*40); if(!pt) return FALSE;
m_hWnd=hWnd;
for(i=39;i>=0;i--)
{
pt[i].x=GetSign()*rand()%m_nXStrength*i/10;
pt[i].y=GetSign()*rand()%m_nYStrength*i/10;
}
return TRUE;
}
Okay, now we have data. Hmm, in other words, we have points where the window should move to. Let us start a thread to move the window.
void JitterWndClass::Shake()
{
PARAMS param;
param.hWnd =m_hWnd;
param.pt =pt;
_beginthread (Thread,0,¶m);
}
unsigned long _beginthread( void( __cdecl *start_address )( void * ),
unsigned stack_size, void *arglist );
We pass a pointer of structure into a thread, so in the thread function we could get the handle of the window we should shake.
At last, we get to shake the window:
void Thread(LPVOID pvoid)
{
int i;
HWND hWnd;
POINT *pt;
hWnd=((PARAMS *)pvoid)->hWnd ; pt=((PARAMS *)pvoid)->pt ;
RECT rect;
POINT op;
::GetClientRect (hWnd,&rect);
op.x=rect.left-10 ;
op.y=rect.top -5;
::ClientToScreen (hWnd,&op);
::PlaySound ("Shake.wav",NULL,SND_FILENAME |SND_ASYNC ); for(i=39;i>=0;i--) {
::SetWindowPos (hWnd,0,op.x +pt[i].x,
op.y+pt[i].y,0,0,SWP_NOSIZE|SWP_NOREPOSITION );
::Sleep (20); }
_endthread (); }
So tired! But so much pleasure! Haha..I hope it could help you, or give you more new ideas.
BUGS And Solution
Thanks "B Joel" for pointing out the bug and method to solve. Really thanks. When I debugged it before, I also encountered the problem of random crash.
Solution: Use the "GetWindowRect()
" instead of the "GetClientRect()
".
Points of Interest
I love computer programming more. I have forgotten to eat for the past few days.
History
- 29th December, 2009: Initial post