类似“99朵玫瑰”的程序开发

 


     近几天,逛网站时,发现有个人想要类似“99朵玫瑰花”的程序,要求是程序运行时,显示指定的图片。闲来无事,用C写了以下的程序。

 

   1. 设置一个WIN32窗口属性为全屏透明的,在该全屏透明的窗口上进行图片文件的显示。该窗口负责接收键盘按键和鼠标按键消息。

        hwnd = CreateWindow(szAppName, NULL, WS_EX_TRANSPARENT, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CXSCREEN), NULL, NULL, hInstance, NULL);

     WS_EX_TRANSPARENT

       这个属性能够使窗口透明,设置了这个属性的窗口的背景使可以被看到的,透明窗口对于鼠标和键盘的消息事件并不是透明的。

     GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)分别用于获取屏幕的x尺寸和y尺寸,即屏幕的宽度和高度.

          (关于Windows窗口层次关系可以参考:http://www.360doc.com/content/10/0415/23/155970_23269174.shtml)

   2. 使图片显示在最顶层,首先考虑的是如何显示一张图片

      CImage cImg;

      cImg.Load(“图片名称”)// 加载图片文件
      HBITMAP hBmp = HBITMAP(cImg);     // 获得bitmap句柄

      HDC hDesktopDC = GetDC(NULL);      // 获取桌面DC句柄
      HDC hMemDC = CreateCompatibleDC(hDesktopDC);  // 创建一个适合hDesktopDC的DC句柄
      SelectObject(hMemDC, hBmp);           // 将hBmp选入该DC

      SetStretchBltMode(hDesktopDC, COLORONCOLOR); // 清除被消除的像素,因为图片缩放时,可能会失真
      // 由于图片的大小有可能很大,而本程序的目的是显示多张图片,并在桌面上随机位置显示,故做了以下处理   

      // 缩放,并随机位置显示,
     StretchBlt(hDesktopDC, rand()%(GetSystemMetrics(SM_CXSCREEN)-180), rand()%(GetSystemMetrics(SM_CYSCREEN)-180*cImg.GetHeight()/cImg.GetWidth()), 180, 
   180*cImg.GetHeight()/cImg.GetWidth(), hMemDC, 0, 0, cImg.GetWidth(), cImg.GetHeight(), SRCCOPY);

    // rand()%(GetSystemMetrics(SM_CXSCREEN)-180), rand()%(GetSystemMetrics(SM_CYSCREEN)-180*cImg.GetHeight()/cImg.GetWidth()), 是图片显示的位置

    // 180,180*cImg.GetHeight()/cImg.GetWidth()是显示的图片最终的大小

     // 之后释放相关的设备上下文句柄以及位图资源
    ReleaseDC(NULL, hMemDC);    
    ReleaseDC(NULL, hDesktopDC);  
    DeleteObject(hBmp);  


 

  3. 需要显示多张图片,将图片都放置到一个文件夹下,接下来要考虑的是如何获取这个文件夹下文件(也就是图片)的名字

   这里要用到FindFirstFile和FindNextFile等函数用于获得文件夹下文件的名称,并将文件数量进行计数,然后将图片进行逐一显示。

   需要设置字符集,对于VS2008可以进行如下设置:解决方案右击-->属性-->配置属性-->常规-->字符集-->未设置。

  获取一个目录下文件名称参考:http://wenwen.soso.com/z/q178975556.htm

  4. 有时候会遇到显示了几张图片后,剩余的图片不显示的问题。

     这是由于图片文件夹中存在Thumbs.db文件,是一个用于Microsoft Windows XPmac os x缓存Windows Explorer的缩略图的文件。Thumbs.db保存在每一个包含图片或照片的目录中。在显示图片之前进行判断,若是该文件就不显示,否则就进行绘制。

  5. 图片显示过程中,似乎不允许打断,即点击键盘或鼠标,图片不会终止显示。

     为此,将图片显示函数作为一个子线程。在消息循环中的WM_CREATE消息下,创建该线程

  _beginthread (ShowPicToDesktop, 0, NULL) ;其中ShowPicToDesktop就是进行图片显示的函数。这样,就解决了上述问题。

 

最后附上程序代码:

 

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <atlimage.h>
#include <mmsystem.h>

#define MAX_RESULT 256

char** EnumFiles(const char *directory, int *count)
{
	WIN32_FIND_DATA FindFileData;  // 用于保存查找到的文件的信息
	HANDLE hFind;
	char result[MAX_RESULT][MAX_PATH]; // 临时保存查找到的文件的文件名
	char **returnresult;  // 用于返回查找的文件文件名
	char pattern[MAX_PATH];  // 查找文件的路径
	int i = 0, j;
	
	// 开始查找
	strcpy(pattern, directory);
	strcat(pattern, "\\*.*");
	CString csPattern(pattern);
	hFind = FindFirstFile(csPattern, &FindFileData);

	if (hFind == INVALID_HANDLE_VALUE) // 若未查找成功
	{
		*count = 0;
		return NULL;
	} 
	else  
	{
		do
		{
			strcpy(result[i], directory);
			strcat(result[i], "\\");
			strcat(result[i++], FindFileData.cFileName);
		}
		while (FindNextFile(hFind, &FindFileData) != 0);
	}
	
	// 查找结束
	FindClose(hFind);

	// 复制到结果中
	returnresult = (char **)calloc(i, sizeof(char *));

	for (j = 0; j < i; j++)
	{
		returnresult[j] = (char *)calloc(MAX_PATH, sizeof(char));
		strcpy(returnresult[j], result[j]);
	}
	
	*count = i;
	return returnresult;
}

void ShowPicToDesktop(PVOID pvoid)  
{  
	int count, i;
	char ** result;
	result = EnumFiles("pic", &count);
	for (i = 2; i < count; i++)
	{
		CImage cImg;
		/*
		Thumbs.db文件是一个数据库,里面保存了这个目录下所有图像文件的缩略图(格式为jpeg)。
		当以缩略图查看时(展示一幅图片或电影胶片) ,将会生成一个Thumbs.db文件。而这种文件
		本程序无法绘制,故增加了下面的第一个判断语句
		*/
		if(strcmp(result[i], "pic\\Thumbs.db")==0)
			continue;
		if(cImg.Load((LPCTSTR)(CString(result[i]))))// 加载图片文件
			return ;  
		HBITMAP hBmp = HBITMAP(cImg);    // 获得bitmap句柄

		HDC hDesktopDC = GetDC(NULL);    // 获取桌面设备上下文句柄
		HDC hMemDC = CreateCompatibleDC(hDesktopDC);  
		SelectObject(hMemDC, hBmp);  

		SetStretchBltMode(hDesktopDC, COLORONCOLOR); // 清除被消除的像素
		// 缩放,并随机位置显示
		StretchBlt(hDesktopDC, rand()%(GetSystemMetrics(SM_CXSCREEN)-180), rand()%(GetSystemMetrics(SM_CYSCREEN)-180*cImg.GetHeight()/cImg.GetWidth()), 180, 
			180*cImg.GetHeight()/cImg.GetWidth(), hMemDC, 0, 0, cImg.GetWidth(), cImg.GetHeight(), SRCCOPY);
		ReleaseDC(NULL, hMemDC);  
		ReleaseDC(NULL, hDesktopDC);  
		DeleteObject(hBmp);  
		::Sleep(700);
	}
}

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)  
{  
	MSG msg;
	static TCHAR szAppName[] = TEXT("Love");
	HWND hwnd;
    WNDCLASS wndclass;
	
	wndclass.style = CS_HREDRAW|CS_VREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = NULL;
	wndclass.hCursor = NULL;
	wndclass.hbrBackground = NULL;
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = szAppName;
	if(!RegisterClass(&wndclass))
	{
		MessageBox(NULL, TEXT("This program is not created"), szAppName, MB_ICONERROR);
		return 0;
	}
	hwnd = CreateWindow(szAppName, NULL, WS_EX_TRANSPARENT, 0, 0,
		GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);
	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);

	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	
	return msg.wParam;  
}  

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{		
	case WM_CREATE:
		PlaySound(TEXT("music//MLH.WAV"), NULL, SND_ASYNC|SND_LOOP); // 异步|循环 播放音频文件
		_beginthread (ShowPicToDesktop, 0, NULL) ;
		return 0;
	case WM_LBUTTONDOWN:
	case WM_RBUTTONDOWN:
	case WM_MBUTTONDOWN:
	case WM_KEYDOWN:
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0; 
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

 需要建立文件夹pic,在此文件夹中放置要显示的图片;文件夹music中放置要播放的wav格式音频文件。并且该音频文件的名称必须是MLH.wav,当然读者可以在代码中进行更改。

 

欢迎各位斧正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值