【C语言】【windows】--圣诞礼物--舞动窗体
erbi_lucifer吧
全部回复
仅看楼主
level 10
堕erbi 楼主

光影的世界……吾为光为影?



2012年02月24日 03点02分 1
level 10
堕erbi 楼主

程序名称:舞动窗体
编译器:vs2010(其它也可以……)
程序大小:817K (添加了图片资源变得好大……[拍砖]
文件包括:舞动窗体.exe,msvcr100.dll
程序界面:

2012年02月24日 03点02分 2
level 10
堕erbi 楼主

好吧……我开始郁闷了……[拍砖]

2012年02月24日 03点02分 3
level 10
堕erbi 楼主
上学期还在学c的控制台编程时在圣诞节收到的礼物中有一个程序,运行时点击按钮,界面消失。然后最上面的程序的窗体开始震动同时播放音乐。好不容易开了任务管理器准备结束进程,结果任务管理器也开始震动起来……[拍砖],按“win徽键+D”显示桌面,结果桌面开始震动……[拍砖],最后等到音乐结束才停止震动,按下右上角“X”准备退出,结果它又开始震动了……[拍砖]
这是那个程序的界面:
当时想要自己写一个,但那时候还没接触c的windows编程,只能放到寒假才开始写,寒假开始自学c的windows SDK编程。
就用到几个函数。
得到最前面窗体的句柄。GetForegroundWindow();
得到窗体的长和宽。GetWindowRect
设置窗体的坐标。MoveWindow
隐藏和显示主窗体。ShowWindow
播放音乐。mciSendStringA
计时器。SetTimer

2012年02月24日 04点02分 4
level 10
堕erbi 楼主

我们按下“开始吧”按钮时……
/*********************************************************************************************
case IDOK :
{
Timerok=TRUE;//可以舞动
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
hThread = CreateThread( NULL,0,ThreadFunc,&dwThrdParam, 0,&dwThreadId);//双线程函数
SetTimer(hwndDlg,0,30,TimerProc); //设置时钟timer
ShowWindow(hwndDlg,SW_HIDE); //窗体变成隐藏形式SW_HIDE
WaitForSingleObject(hThread,-1); //等待线程结束
}
break;
/*********************************************************************************************
1) 函数:SetTimer(放timer窗体的句柄,timer的ID,时间间隔(毫秒),timer的消息处理函数)
2) 函数:ShowWindow(要改变形式的窗体的句柄,形式)
3) 函数:WaitForSingleObject(等待的线程,等待时间(-1是表示一直等到结束))
[少林寺]
2012年02月24日 04点02分 5
level 10
堕erbi 楼主

【线程函数】
创建的线程:
/*********************************************************************************************
DWORD WINAPI ThreadFunc( LPVOID lpParam ) //线程函数
{
mciSendStringA("play \\2.mp3","",0,NULL);
return 0;
}
/*********************************************************************************************
函数mciSendStringA:播放音乐
mciSendStringA(“play 音乐文件路径+文件名”,字符数组,字符数组大小,句柄);
在这里只需要简单的音乐直接播放功能,于是字符数组省略,句柄为NULL,’\\’是表示当前目录下的文件……
我们按下“开始吧”按钮后,创建线程,开始播放音乐……
2012年02月24日 04点02分 6
level 10
堕erbi 楼主

舞动窗体的主要三点:获得最前面窗体的句柄,获得该窗体的坐标,移动该窗体……[揉脸]
舞动的效果:每间隔一小段时间(如30毫秒),移动一次窗体,如:向右移动两次后在向左移动4次接着再向左移动4次……这样不断来回移动,因为时间间隔短于是出现了窗体抖动的现象……
首先 :HWND HWNDF = GetForegroundWindow(); //得到最前面窗体的句柄,保存在定义的HWNDF变量里……
接着获取坐标:
先定义
RECT LPRECTlpRect1;
ZeroMemory(&LPRECTlpRect1,sizeof(LPRECTlpRect1));//C语言中定义结构体都要先初始化,用ZeroMemory(结构体变量,结构体变量的大小)
再得到坐标:::GetWindowRect(HWNDF,&LPRECTlpRect1);
GetWindowRect(要得到坐标的窗体的句柄,存放坐标的结构体)
[打酱油]

2012年02月24日 04点02分 7
level 10
堕erbi 楼主
[抖胸]
LPRECTlpRect1是一个RECT变量,我们来看看它的原型:
typedef struct tagRECT
{
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;
从中我们可以看到窗体左上角的坐标是(left,top),右下角的坐标是(right,bottom)
它们都是long类型变量……
因为舞动时只需改变窗体在屏幕上的位置,于是把窗体的左上角的坐标取出来,然后改变它……
long x =LPRECTlpRect1.left ,y=LPRECTlpRect1.top ;
/*********************************************************************************************
if(Timerok==TRUE){ //如果可以抖动那就……
c++; //计时,用于在音乐停止时停止舞动
x=x+a;y=y+b; //改变坐标大小
if(x>20||y>20){a=-a;b=-b;} //移动后改变移动方向……
if(x<-20||y<-20){a=-a;b=-b;}
MoveWindow(HWNDF, x,y ,(LPRECTlpRect1.right-LPRECTlpRect1.left) ,(LPRECTlpRect1.bottom-LPRECTlpRect1.top) ,FALSE); //开始移动
}
/*********************************************************************************************
移动窗体的函数:MoveWindow(要移动的窗体的句柄,坐标X,坐标Y,窗体宽,窗体高,不立刻执行(将消息放到队列中))
这个是timer的消息函数,也就是说每个一段时间(这里是30毫秒),执行一次函数……
于是窗体不断左右移动……
[抖胸]
2012年02月24日 04点02分 8
level 10
堕erbi 楼主

接着是计时:
/*********************************************************************************************
if(c>2500){
ShowWindow(hwnd,SW_SHOWNA); //显示主窗体
Timerok=FALSE; //不能抖动
c=0; //从新计时
}
/*********************************************************************************************
你可以根据你的音乐的播放时间来计算:播放时间/(时间间隔,在这里是(1000/30秒)),然后可以自己调整…… [正Music]
2012年02月24日 04点02分 9
level 10
堕erbi 楼主

最后是按下右上方的‘X’时,弹窗不让你关闭,再次舞动窗体&……
我们看看取消按钮和(右上角的关闭)的消息:
/*********************************************************************************************
case IDCANCEL:
{
static int forexit=0; //计算你按下关闭按钮的次数
if(forexit<2){ //头两次按就
int a=MessageBox(hwndDlg,_T("想要退出?"),_T("提示"),MB_OKCANCEL|MB_ICONQUESTION); //弹窗询问
if(a==IDOK) //如果你再按下确定,那么就……
{
MessageBox(hwndDlg,_T("门都没有!!!>_<……"),_T("
哈哈"),MB_OK|MB_ICONERROR); //继续弹窗
//以下和IDOK的消息差不多,再次创建线程和timer,再次舞动
Timerok=TRUE;
c=0;
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
hThread = CreateThread( NULL,0,ThreadFunc,&dwThrdParam, 0,&dwThreadId);
ShowWindow(hwndDlg,SW_HIDE);
SetTimer(hwndDlg,0,30,TimerProc);
WaitForSingleObject(hThread,-1);
forexit++; //按钮按下记录增加一次
}
}
else{ //第三次按下那么久放过你吧……真正的退出……
EndDialog(hwndDlg, IDCANCEL);
}
}
break;
/*********************************************************************************************

2012年02月24日 04点02分 10
level 10
堕erbi 楼主
[顶]
注意:播放音乐要添加头文件和连接文件lib(告诉编译器要用的外部函数在那个dll里)……
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")

2012年02月24日 04点02分 11
level 10
堕erbi 楼主

/*********************************************************************************************
开始全部代码吧!
[Yeah]
/*********************************************************************************************
/*********************************************************************************************
头文件,连接库,全局变量
/*********************************************************************************************
#include <tchar.h>
#include <Windows.h>
#include "resource.h"
#include <Winuser.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
bool Timerok=FALSE;
int c=0;
2012年02月24日 04点02分 12
level 10
堕erbi 楼主

/*********************************************************************************************
时间处理函数[晕厥]
/*********************************************************************************************
VOID CALLBACK TimerProc(HWND hwnd,UINT message,UINT timerID,DWORD TIME)
{
static int a=10,b=10;
RECT LPRECTlpRect1;
ZeroMemory(&LPRECTlpRect1,sizeof(LPRECTlpRect1));
HWND HWNDF = GetForegroundWindow();
::GetWindowRect(HWNDF,&LPRECTlpRect1);
long x =LPRECTlpRect1.left ,y=LPRECTlpRect1.top ;
if(Timerok==TRUE){
c++;
x=x+a;y=y+b;
if(x>20||y>20){a=-a;b=-b;}
if(x<-20||y<-20){a=-a;b=-b;}
MoveWindow(HWNDF, x,y ,(LPRECTlpRect1.right-LPRECTlpRect1.left) ,(LPRECTlpRect1.bottom-LPRECTlpRect1.top) ,FALSE);
}
if(c>2500){
ShowWindow(hwnd,SW_SHOWNA);
Timerok=FALSE;
c=0;
}
}
2012年02月24日 04点02分 13
level 10
堕erbi 楼主

/*********************************************************************************************
线程函数[睡觉]
/*********************************************************************************************
DWORD WINAPI ThreadFunc( LPVOID lpParam ) //线程函数{
mciSendStringA("play \\2.mp3","",0,NULL);
return 0;
}

2012年02月24日 04点02分 14
level 10
堕erbi 楼主

/*********************************************************************************************
窗体消息处理函数[睡觉]
/*********************************************************************************************
INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int FONTsty=0;
switch(uMsg)
{
case WM_INITDIALOG :
{
}
break;
case WM_COMMAND :
{
switch (wParam)
{
case IDCANCEL:
{
static int forexit=0;
if(forexit<2){
int a=MessageBox(hwndDlg,_T("想要退出?"),_T("提示"),MB_OKCANCEL|MB_ICONQUESTION);
if(a==IDOK)
{
MessageBox(hwndDlg,_T("门都没有!!!>_<……"),_T("哈哈"),MB_OK|MB_ICONERROR);
Timerok=TRUE;
c=0;
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
hThread = CreateThread( NULL,0,ThreadFunc,&dwThrdParam, 0,&dwThreadId);
ShowWindow(hwndDlg,SW_HIDE);
SetTimer(hwndDlg,0,30,TimerProc);
WaitForSingleObject(hThread,-1);
forexit++;
}
}
else{
EndDialog(hwndDlg, IDCANCEL);
}
}
break;
case IDOK :
{
Timerok=TRUE;
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
hThread = CreateThread( NULL,0,ThreadFunc,&dwThrdParam, 0,&dwThreadId);
SetTimer(hwndDlg,0,30,TimerProc);
ShowWindow(hwndDlg,SW_HIDE);
WaitForSingleObject(hThread,-1);
}
break;
case IDC_ABOUT:
{
MessageBox(hwndDlg,_T("试手的程序……O(∩_∩)O哈哈~,终于做出来了……\n公司:Erbi-lucifer \n作者:【Erbi-lucifer:光影】 \n时间:2012年1月22日20:26:57"),_T("光影软件"),MB_OK);
}
break;
default:break;
}
default:break;
}
} return 0;
}

2012年02月24日 04点02分 15
level 10
堕erbi 楼主

/*********************************************************************************************
万年不变主函数[睡觉]
/*********************************************************************************************
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
return 0;
}

2012年02月24日 04点02分 16
level 10
堕erbi 楼主
这个看懂了估计就会了……https://tieba.baidu.com/p/1420705179
[Yeah]
2012年03月06日 05点03分 19
1