搞事开始。
首先,我们先进行如下声明
#include #include #include #include HDC offscreen;
long double param;
COLORREF C_TRANSPARENT=RGB(1,2,3);
COLORREF C_RED=RGB(255,0,0);
这里并没有什么值得注意的地方。
offscreen是我们绘制心形的一个小的“画布”;而param则是绘制心形所用到的参数。
接下来,既然需要显示一个心,那么,我们需要一个绘制心形的“画布”。
因此,我们需要准备一个窗体。
HWND InitWindow(){
RECT rect;
HWND desktop=GetDesktopWindow();
GetWindowRect(desktop,&rect);
int width=rect.right-rect.left;
int height=rect.bottom-rect.top;
int mysize=(width
WNDCLASSEXW wndclass = { 0 };
wndclass.cbSize=sizeof(WNDCLASSEXW);
wndclass.lpfnWndProc = (WNDPROC)DefWindowProc;
wndclass.hInstance = GetModuleHandle(NULL);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclass.lpszClassName = L"Heart";
if (RegisterClassExW(&wndclass) == NULL)
return NULL;
HWND hWnd = CreateWindowExW(
WS_EX_LAYERED|WS_EX_TOPMOST|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW,
L"Heart", L"title",
WS_POPUP|WS_VISIBLE,
width/2-mysize/2,height/2-mysize/2,mysize,mysize,
NULL, NULL, GetModuleHandle(NULL), NULL
);
if (!hWnd)
return NULL;
SetLayeredWindowAttributes(hWnd,C_TRANSPARENT,200,LWA_ALPHA | LWA_COLORKEY);
return hWnd;
}
这里,我们将C_TRANSPARENT指定为“透明色”。这也是为了后期的效果。
再接下来,我们编写在窗体上绘制心形的函数。这一部分是简单的,因为只是把offscreen上的图形复制到窗体上。甚至可以直接从随便什么地方抄到。
void ShowImage(HWND hWnd,HDC offscreen){
RECT rect;
GetWindowRect(hWnd,&rect);
HDC dc=GetWindowDC(hWnd);
BitBlt(dc,0,0,rect.right-rect.left,rect.bottom-rect.top,offscreen,0,0,SRCCOPY);
}
然后,为整个窗体编写事件循环。
void RunWindow(HWND hWnd){
MSG msg;
while (1) {
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE)
{
if (GetMessage(&msg, NULL, 0, 0))
{
if(msg.message==WM_PAINT){
ShowImage(msg.hwnd,offscreen);
continue;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
return;
}
}
if (!IsWindow(hWnd))break;
Sleep(50);
}
}
好了,废话说完,接下来我们进入正题,即心形的构造。
首先,因为“名字”这个东西并不是很适合数值化。因此,我们对名字进行哈希变换,并与内置的哈希值进行比对,从而得到某个value值。
这里我们用到了Windows内置的Hash算法
void CalcPara(void* data,size_t cbdata){
const BYTE key[]=
{0x95,0x34,0xf3,0x1b,0xde,0x49,0xd1,0x40,0x95,0x26,0x8b,0xd6,0xc1,0x38,0xc1,0x2e,0xef,0x2f,0x35,0xc1};
HCRYPTPROV prov;
CryptAcquireContextA(&prov,NULL,NULL,PROV_RSA_AES,CRYPT_SILENT|CRYPT_VERIFYCONTEXT);
HCRYPTHASH hash;
CryptCreateHash(prov,CALG_SHA1,0,0,&hash);
CryptHashData(hash,(BYTE*)data,cbdata,NULL);
DWORD hashsize;
DWORD tmp=sizeof(DWORD);
CryptGetHashParam(hash,HP_HASHSIZE,(BYTE*)&hashsize,&tmp,0);
BYTE* hval=(BYTE*)malloc(hashsize);
memset(hval,0,hashsize);
tmp=hashsize;
CryptGetHashParam(hash,HP_HASHVAL,(BYTE*)hval,&tmp,0);
if(tmp
int diff=hashsize<20?20-hashsize:hashsize-20;
for(int i=0;i<(hashsize<20?hashsize:20);i++)
if(hval[i]!=key[i])
diff++;
param=diff/2;
if(param>2)
param=2;
}
接下来,我们开始对图形进行绘制。
定义如下函数。
int GenFigure(long double x,long double y){
return 17*x*x+16*y*abs(x)+17*y*y +param/abs(10*x+sin(15*y))< 8;
}
有关此函数的内容会在文末的参考文献中予以列出。
接下来,我们用这样的函数对某个bitmap中的每一个像素进行初始化。
void InitBitmap(HWND hWnd,int (*figure)(long double,long double)){
RECT rect;
GetWindowRect(hWnd,&rect);
int width=rect.right-rect.left;
int height=rect.bottom-rect.top;
HDC dc=GetWindowDC(hWnd);
offscreen=CreateCompatibleDC(dc);
HBITMAP bitmap=CreateCompatibleBitmap(dc,width,height);
SelectObject(offscreen,bitmap);
for(int i=0;i
for(int j=0;j
if(figure((long double)(i)*2/width-1,(long double)(j)*2/height-1))
SetPixel(offscreen,i,j,C_RED);
else
SetPixel(offscreen,i,j,C_TRANSPARENT);
}
最后,把这一切整合起来,就得到了“绘制心型”的程序。
int main()
{
wchar_t name[64];
memset(name,0,64*sizeof(wchar_t));
scanf("%S",name);
HWND chwnd=GetConsoleWindow();
#ifndef _DEBUG
ShowWindow(chwnd,SW_HIDE);
#endif
CalcPara(name,64*sizeof(wchar_t));
HWND hwnd=InitWindow();
RECT rect;
int width,height;
InitBitmap(hwnd,&GenFigure);
RunWindow(hwnd);
}
这样,我们得到了一个“输入正确的名字则绘制心形”的程序。
运行效果如图。
输入错误的名字
输入正确的名字
至此,我该滚去写作业了。