用VB制做可换图片的屏幕保护程序

2024-12-01 23:14:05
推荐回答(5个)
回答1:

VC++可谓神通广大,如果学到家了,或者就掌握了那么一点MFC,你也会感到它的方便快捷,当然最重要的是功能强大。不是吗,从最基本的应用程序.EXE到动态连接库DLL,再由风靡网上的ActiveX控件到Internet Server API,当然,还有数据库应用程序……瞧,我都用它来做屏幕保护程序了。一般的屏幕保护程序都是以SCR作为扩展名,并且要放在c:\windows 目录或 c:\windows\system 目录下,由Windows 98内部程序调用(Windows NT 是在 c:\windows\system32 目录下)。怎么调用?不用说了,这谁不知道。

好了,我们来作一个简单的。选择MFC AppWizard(exe),Project Name 为MyScreensaver,[NEXT],对话框,再后面随你了。打开菜单Project、Settings,在Debug页、Executable for debug session项,以及Link页中Output file name项改为c:\windows\MyScreensaver.scr,这样,你可以调试完后,直接在VC中运行(Ctrl+F5),便可看到结果。当然,这样做的唯一缺点是你必须手动清除Windows 目录下的垃圾文件(当然是在看到满意结果后;还有,你可借助SafeClean 这个小东东来帮你清除,除非你的硬盘大的让你感到无所谓……快快快回来,看我跑到那里去了)。接下来用Class Wizard生成CMyWnd类,其基类为CWnd(在Base Class 中为generic CWnd)。这个类是我们所要重点研究的。创建满屏窗口、计时器,隐藏鼠标,展示图片,响应键盘、鼠标等等,这家伙全包了。至于MyScreensaverDlg.h与MyScreensaverDlg.cpp文件我们暂时不管。打开MyScreensaver.cpp,修改InitInstance()函数:

BOOL CMyScreensaverApp::InitInstance()

{

AfxEnableControlContainer();

#ifdef _AFXDLL

Enable3dControls(); // Call this when using MFC in a shared DLL

#else

Enable3dControlsStatic(); // Call this when linking to MFC statically

#endif

CMyWnd* pWnd = new CMyWnd;

pWnd->Create();

m_pMainWnd = pWnd;

return TRUE;

}

当然,再这之前得先 #include “MyWnd.h" 。后面要做的都在MyWnd.h 与 MyWnd.cpp 两文件中了。

下面给出CMyWnd 的说明:

class CMyWnd : public CWnd

{

public:

CMyWnd();

static LPCSTR lpszClassName; //注册类名

public:

BOOL Create();

public:

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CMyWnd)

protected:

virtual void PostNcDestroy();

//}}AFX_VIRTUAL

public:

virtual ~CMyWnd();

protected:

CPoint m_prePoint; //检测鼠标移动

void DrawBitmap(CDC& dc, int nIndexBit);

//{{AFX_MSG(CMyWnd)

afx_msg void OnPaint();

afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

afx_msg void OnMButtonDown(UINT nFlags, CPoint point);

afx_msg void OnMouseMove(UINT nFlags, CPoint point);

afx_msg void OnRButtonDown(UINT nFlags, CPoint point);

afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

afx_msg void OnDestroy();

afx_msg void OnTimer(UINT nIDEvent);

afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);

afx_msg void OnActivateApp(BOOL bActive, HTASK hTask);

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

MyWnd.cpp 文件:

……

CMyWnd::CMyWnd()

{

m_prePoint=CPoint(-1, -1);

}

LPCSTR CMyWnd::lpszClassName=NULL;

BOOL CMyWnd::Create()

{

if(lpszClassName==NULL)

{

lpszClassName=AfxRegisterWndClass(CS_HREDRAW CS_VREDRAW,

::LoadCursor(AfxGetResourceHandle(),MAKEINTRESOURCE(IDC_NOCURSOR)));

//注册类;IDC_NOCURSOR为新建光标的ID,这个光标没有任何图案

}

CRect rect(0, 0, ::GetSystemMetrics(SM_CXSCREEN),

::GetSystemMetrics(SM_CYSCREEN));

CreateEx(WS_EX_TOPMOST, lpszClassName, _T(“”), WS_VISIBLE WS_POPUP,

rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,

GetSafeHwnd(), NULL, NULL); //创建一个全屏窗口

SetTimer(ID_TIMER, 500, NULL);//计时器,ID_TIMER别忘了定义

return TRUE;

}

为了防止同时运行两个相同的程序,下面两个函数是必需的:

void CMyWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)

{

CWnd::OnActivate(nState,pWndOther,bMinimized);

if (nState==WA_INACTIVE)

PostMessage(WM_CLOSE);

}

void CMyWnd::OnActivateApp(BOOL bActive, HTASK hTask)

{

CWnd::OnActivateApp(bActive, hTask);

if (!bActive) //is being deactivated

PostMessage(WM_CLOSE);

}

OnPaint()函数将全屏窗口置为黑色:

void CMyWnd::OnPaint()

{

CPaintDC dc(this);

CBrush brush(RGB(0,0,0));

CRect rect;

GetClientRect(rect);

dc.FillRect(&rect, &brush);

}

由计数器调用DrawBitmap()函数,切换图片;注意,下面两个函数中的IDB_BITMAP1, dc.BitBlt(0,0,800,600……以及if(nIndexBit>=5)中的有关数据依据你的bmp图片个数、尺寸、位置不同而不同,我是选择了5张800x600的bmp图片。注意,ID值是连续的,IDB_BITMAP1最小。

void CMyWnd::DrawBitmap(CDC &dc, int nIndexBit)

{

CDC dcmem;

dcmem.CreateCompatibleDC(&dc);

CBitmap m_Bitmap;

m_Bitmap.LoadBitmap(IDB_BITMAP1+nIndexBit);

dcmem.SelectObject(m_Bitmap);

dc.BitBlt(0,0,800,600,&dcmem,0,0,SRCCOPY);

}

void CMyWnd::OnTimer(UINT nIDEvent)

{

CClientDC dc(this);

static nIndexBit=0;

if(nIndexBit>=5)

nIndexBit=0;

DrawBitmap(dc, nIndexBit++);

CWnd::OnTimer(nIDEvent);

}

响应键盘、鼠标是屏幕保护程序不可缺少的,在OnKeyDown()、 OnLButtonDown()、 OnMButtonDown()、OnRButtonDown()、OnSysKeyDown()函数中都加入:

PostMessage(WM_CLOSE);

OnMouseMove()函数比较特殊,它应加的代码为:

if(m_prePoint == CPoint(-1,-1))

m_prePoint = point;

else if(m_prePoint!=point)

PostMessage(WM_CLOSE);

快要完工了。在OnDestroy()函数中删掉计时器:KillTimer(ID_TIMER);

还有啦,在CMyWnd::PostNcDestroy() 中加入: delete this;

哎呀,腰酸背疼,眼球发涩,手背奇麻(不会吧)!不过,相信你一定会迫不及待地按下Ctrl+F5, 看着一幅幅图片在你面前轮番展示,啊,自己的屏幕保护程序!赶快赶快,换上自制的屏保,感觉就是不一样:图片任你挑,时间间隔任你改,鼠标?键盘?我想响应谁就响应谁……哎呀,谁扔的纸团:(。

其实,上面的程序还有很多可以改进的地方,比如图片总是单一地显示;bmp 文件太大,导致生成的屏幕保护程序也很大,远没有jpg合算;没有密码,没有可直接控制的界面。由于InitInstance()函数的简单处理(直接调用CMyWnd类),你会发现当你在桌面上右击,选择“属性”、“屏幕保护程序”页、“屏幕保护程序”下拉菜单、选中MyScreensaver时,MyScreensaver就直接预览了(或是直接运行了);假设你确定MyScreensaver作为你的屏幕保护程序,等你第二次进入“屏幕保护程序”页时,就直接预览。Why? 回头看看InitInstance()函数就明白了。为了让它更听话地工作,可修改InitInstance()函数:

LPTSTR lpszArgv = __argv[1];

if (lpszArgv[0] ==‘/’)

lpszArgv++;

if (lstrcmpi(lpszArgv, _T(“s”))==0)

{

CMyWnd* pWnd=new CMyWnd;

pWnd->Create();

m_pMainWnd=pWnd;

return TRUE;

}

return FALSE;

不过现在你要是再在VC中运行这个程序,“该程序执行了非法操作,即将关闭。将会伴随着一超重低音供你欣赏。(啊?)原因是我们加了一句return FALSE; 还有,别忘了还有一个CMyScreensaverDlg类没有用上,用它来与你的屏保直接对话再好不过了。例如,为了方便地确定时间间隔,选取图片,加上一个编辑框和几个按钮就可以了。重申一点,由于生成文件较大,占用的内存也多,如果不能运行,很可能是开的窗口太多了。这时你可以换较小的图片。

回答2:

'我也写个吧
'======================
'新建一个窗体: form1
'将form1.BorderStyle 属性设置成 0
'添加一个时间控件: timer1
'一个Filelistbox控件:File1

'以下是代码
'声明
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function ShowCursor Lib "user32" (ByVal bShow As Long) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Const SW_SHOWMAXIMIZED = 3
Dim kaiguan As Boolean
Dim PictureNum As Long

Private Sub Form_Load()
ShowWindow Me.hwnd, SW_SHOWMAXIMIZED
kaiguan = False
Timer1.Interval = 2000
File1.Path = "C:\Documents and Settings\All Users\Documents\My Pictures\示例图片" '放置图片的文件夹
File1.Pattern = "*.jpg;*.bmp;*.gif" '图片格式
Form1.Picture = LoadPicture(File1.Path & "\" & File1.List(PictureNum)) '先载入第一张
File1.Visible = False
PictureNum = 1
ShowCursor False
SetWindowPos Me.hwnd, -1, 0, 0, 0, 0, 3 '窗体在最上面
End Sub

'按键 和鼠标使程序结束
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If kaiguan Then End
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If kaiguan Then End
End Sub

'换图片
Private Sub Timer1_Timer()
If kaiguan = False Then
Timer1.Interval = 2000
kaiguan = True
End If
picturefile = File1.Path & "\" & File1.List(PictureNum)
Form1.Picture = LoadPicture(picturefile)
PictureNum = PictureNum + 1
If PictureNum >= File1.ListCount Then PictureNum = 0
End Sub

回答3:

'要生成文件的后缀名为scr
'窗体样式要改为Me.BorderStyle = 0
Dim X1, Y1, X2, Y2 As Integer
Dim I As Integer
Dim J As Boolean
Dim K As Integer

Dim WithEvents Label1 As Label '声明一个label
Dim WithEvents Timer1 As Timer '声明一个timer

Private Sub Form_Activate()
I = 100
K = 100
X1 = Me.Width / 2
Y1 = Me.Height / 3
X2 = X1
Y2 = Y1

Rem 设置label的位置
Label1.Top = Me.Height / 2 - Label1.Height / 2
Label1.Left = Me.Width / 2 - Label1.Width / 2
End Sub

Private Sub Form_Load()
Me.BackColor = &H0& '窗体的背景色为黑色
Me.FillColor = RGB(Rnd * 255, Rnd * 255, Rnd * 255) '窗体的填充色为随机
Me.ForeColor = RGB(Rnd * 255, Rnd * 255, Rnd * 255) '窗体的前景色为随机
Me.DrawMode = 13 '窗体输出的外观为13
Me.DrawWidth = 2 '窗体输出的线条宽度为2
Me.FillStyle = 7 '窗体的填充样式为7

Set Label1 = Me.Controls.Add("VB.Label", "Label1") '设置label
Set Timer1 = Me.Controls.Add("VB.Timer", "Timer1") '设置timer

Label1.Visible = True 'label可见性为true
Label1.AutoSize = True 'label自动调整大小
Label1.BackStyle = 0 'label背景色为透明
Label1.Caption = "I LOVE YOU" '设置标题
Label1.Font.Size = 60 '字体大小为60
Label1.ForeColor = &HFF00& 'label前景色为黑色

Timer1.Enabled = True 'timer为有效
Timer1.Interval = 10 'timer时间 间隔为0.001秒

Me.WindowState = 2 '窗体展开样式
End Sub

Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Static currentX, currentY As Single
Dim orignX, orignY As Single
'把当前的鼠标值赋给orignX和orignY
orignX = X
orignY = Y
'初始化currentX和currentY
If currentX = 0 And currentY = 0 Then
currentX = orignX
currentY = orignY
Exit Sub
End If
If Abs(orignX - currentX) > 1 Or Abs(orignY - currentY) > 1 Then
End
End If
End Sub

Private Sub Timer1_Timer()
Me.Circle (X1, Y1), 250 '在窗体上画圆
Me.Circle (X2, Y2), 250 '在窗体上画圆

If Y1 <= Me.Height - 1200 Then '在指定高度运行
X1 = X1 + K
Y1 = Y1 - I
X2 = X2 - K
Y2 = Y2 - I
I = I - 2
If Y1 <= Me.Height / 3 Then
K = K - 1
ElseIf Y1 >= Me.Height / 3 Then
K = K - 5
End If
Else
I = 100
K = 100
X1 = Me.Width / 2
Y1 = Me.Height / 3
X2 = X1
Y2 = Y1

Me.FillColor = RGB(Rnd * 255, Rnd * 255, Rnd * 255) '窗体的填充色为随机
Me.ForeColor = RGB(Rnd * 255, Rnd * 255, Rnd * 255) '窗体的前景色为随机

End If

Me.DrawWidth = 3 '窗体输出的线条宽度为3
'在窗体上随机画点
Me.PSet (Rnd * Me.Width, Rnd * Me.Height), RGB(Rnd * 225, Rnd * 225, Rnd * 225)
Me.DrawWidth = 2 '窗体输出的线条宽度为2
End Sub
''''''''''''''''''''''''''''''
'在窗体上单击鼠标时退出程序
Private Sub Form_Click()
End
End Sub
'在窗体上按下按键时退出程序
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
End
End Sub

'在窗体上移动鼠标时退出程序
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Static currentX, currentY As Single
Dim orignX, orignY As Single
'把当前的鼠标值赋给orignX和orignY
orignX = X
orignY = Y
'初始化currentX和currentY
If currentX = 0 And currentY = 0 Then
currentX = orignX
currentY = orignY
Exit Sub
End If
If Abs(orignX - currentX) > 1 Or Abs(orignY - currentY) > 1 Then
End
End If
End Sub

回答4:

可以随意增减图片!
Private Sub P1_Click()
Static a%
a = a + 1
If a = 1 Then
Picture = LoadPicture("图片的路径")
End If
If a = 2 Then
Picture = LoadPicture("图片的路径")
End If
If a = 3 Then
Picture = LoadPicture("图片的路径")
End If
If a = 4 Then
Picture = LoadPicture("图片的路径")
End If
If a = 5 Then
Picture = LoadPicture("图片的路径")
End If
If a = 6 Then
Picture = LoadPicture("图片的路径")
End If
If a = 7 Then
a = 0
End If
If a = 0 Then
Picture = LoadPicture()
End If
End Sub

回答5:

VB.net还是 VB6.0
就用个图片框装图片,把窗体的边框什么去掉,生成.exe后改拓展名