📄 subject_24785.htm
字号:
<p>
序号:24785 发表者:CDMA2000 发表日期:2002-12-16 15:12:59
<br>主题:如何编写屏幕保护程序(生成.scr)文件?有无资料?还有如何在代码中执行屏幕保护文件(*.scr)
<br>内容:我记得好象是rundll32.exe来执行的,但不能确定有人帮以下吗?
<br><a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p>
<hr size=1>
<blockquote><p>
回复者:bird 回复日期:2002-12-16 15:28:33
<br>内容:http://www.cbinews.com/developer/showcontent.php?articleid=2195<BR>http://www.vckbase.com/code/listcode.asp?mclsid=13&sclsid=1329<BR>看代码:<BR>http://my.szptt.net.cn/twing/landown/exam/exam003.zip
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
<font color=red>答案被接受</font><br>回复者:bird 回复日期:2002-12-16 15:32:15
<br>内容: VC++可谓神通广大,如果学到家了,或者就掌握了那么一点MFC,你也会感到它的方便快捷,当然最重要的是功能强大。不是吗,从最基本的应用程序.EXE到动态连接库DLL,再由风靡网上的ActiveX控件到Internet Server API,当然,还有数据库应用程序……瞧,我都用它来做屏幕保护程序了。一般的屏幕保护程序都是以SCR作为扩展名,并且要放在c:\windows 目录或 c:\windows\system 目录下,由Windows 98内部程序调用(Windows NT 是在 c:\windows\system32 目录下)。怎么调用?不用说了,这谁不知道。<BR> 好了,我们来作一个简单的。选择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()函数:<BR> BOOL CMyScreensaverApp::InitInstance()<BR> {<BR> AfxEnableControlContainer();<BR> #ifdef _AFXDLL<BR> Enable3dControls(); // Call this when using MFC in a shared DLL<BR> #else<BR> Enable3dControlsStatic(); // Call this when linking to MFC statically<BR> #endif<BR> CMyWnd* pWnd = new CMyWnd;<BR> pWnd->Create();<BR> m_pMainWnd = pWnd;<BR> return TRUE;<BR> }<BR> 当然,再这之前得先 #include “MyWnd.h" 。后面要做的都在MyWnd.h 与 MyWnd.cpp 两文件中了。<BR> 下面给出CMyWnd 的说明:<BR> class CMyWnd : public CWnd<BR> {<BR> public:<BR> CMyWnd();<BR> static LPCSTR lpszClassName; //注册类名<BR> public:<BR> BOOL Create();<BR> public:<BR> // ClassWizard generated virtual function overrides<BR> //{{AFX_VIRTUAL(CMyWnd)<BR> protected:<BR> virtual void PostNcDestroy();<BR> //}}AFX_VIRTUAL<BR> public:<BR> virtual ~CMyWnd();<BR> protected:<BR> CPoint m_prePoint; //检测鼠标移动<BR> void DrawBitmap(CDC& dc, int nIndexBit);<BR> //{{AFX_MSG(CMyWnd)<BR> afx_msg void OnPaint();<BR> afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);<BR> afx_msg void OnLButtonDown(UINT nFlags, CPoint point);<BR> afx_msg void OnMButtonDown(UINT nFlags, CPoint point);<BR> afx_msg void OnMouseMove(UINT nFlags, CPoint point);<BR> afx_msg void OnRButtonDown(UINT nFlags, CPoint point);<BR> afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);<BR> afx_msg void OnDestroy();<BR> afx_msg void OnTimer(UINT nIDEvent);<BR> afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);<BR> afx_msg void OnActivateApp(BOOL bActive, HTASK hTask);<BR> //}}AFX_MSG<BR> DECLARE_MESSAGE_MAP()<BR> };<BR> MyWnd.cpp 文件:<BR> ……<BR> CMyWnd::CMyWnd()<BR> {<BR> m_prePoint=CPoint(-1, -1);<BR> } <BR> LPCSTR CMyWnd::lpszClassName=NULL;<BR> BOOL CMyWnd::Create()<BR> {<BR> if(lpszClassName==NULL)<BR> {<BR> lpszClassName=AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW, <BR> ::LoadCursor(AfxGetResourceHandle(),MAKEINTRESOURCE(IDC_NOCURSOR)));<BR> //注册类;IDC_NOCURSOR为新建光标的ID,这个光标没有任何图案<BR> }<BR> CRect rect(0, 0, ::GetSystemMetrics(SM_CXSCREEN),<BR> ::GetSystemMetrics(SM_CYSCREEN));<BR> CreateEx(WS_EX_TOPMOST, lpszClassName, _T(“”), WS_VISIBLE|WS_POPUP, <BR> rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, <BR> GetSafeHwnd(), NULL, NULL); //创建一个全屏窗口<BR> SetTimer(ID_TIMER, 500, NULL);//计时器,ID_TIMER别忘了定义<BR> return TRUE;<BR> }<BR> 为了防止同时运行两个相同的程序,下面两个函数是必需的:<BR> void CMyWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) <BR> {<BR> CWnd::OnActivate(nState,pWndOther,bMinimized);<BR> if (nState==WA_INACTIVE)<BR> PostMessage(WM_CLOSE);<BR> }<BR> void CMyWnd::OnActivateApp(BOOL bActive, HTASK hTask)<BR> {<BR> CWnd::OnActivateApp(bActive, hTask);<BR> if (!bActive) //is being deactivated<BR> PostMessage(WM_CLOSE);<BR> }<BR> OnPaint()函数将全屏窗口置为黑色:<BR> void CMyWnd::OnPaint()<BR> {<BR> CPaintDC dc(this);<BR> CBrush brush(RGB(0,0,0));<BR> CRect rect;<BR> GetClientRect(rect);<BR> dc.FillRect(&rect, &brush);<BR> }<BR> 由计数器调用DrawBitmap()函数,切换图片;注意,下面两个函数中的IDB_BITMAP1, dc.BitBlt(0,0,800,600……以及if(nIndexBit>=5)中的有关数据依据你的bmp图片个数、尺寸、位置不同而不同,我是选择了5张800x600的bmp图片。注意,ID值是连续的,IDB_BITMAP1最小。<BR> void CMyWnd::DrawBitmap(CDC &dc, int nIndexBit)<BR> {<BR> CDC dcmem;<BR> dcmem.CreateCompatibleDC(&dc);<BR> CBitmap m_Bitmap;<BR> m_Bitmap.LoadBitmap(IDB_BITMAP1+nIndexBit);<BR> dcmem.SelectObject(m_Bitmap);<BR> dc.BitBlt(0,0,800,600,&dcmem,0,0,SRCCOPY);<BR> }<BR> void CMyWnd::OnTimer(UINT nIDEvent)<BR> {<BR> CClientDC dc(this);<BR> static nIndexBit=0;<BR> if(nIndexBit>=5)<BR> nIndexBit=0;<BR> DrawBitmap(dc, nIndexBit++);<BR> CWnd::OnTimer(nIDEvent);<BR> }<BR> <BR> 响应键盘、鼠标是屏幕保护程序不可缺少的,在OnKeyDown()、 OnLButtonDown()、 OnMButtonDown()、OnRButtonDown()、OnSysKeyDown()函数中都加入:<BR> PostMessage(WM_CLOSE);<BR> OnMouseMove()函数比较特殊,它应加的代码为:<BR> if(m_prePoint == CPoint(-1,-1))<BR> m_prePoint = point;<BR> else if(m_prePoint!=point)<BR> PostMessage(WM_CLOSE); <BR> 快要完工了。在OnDestroy()函数中删掉计时器:KillTimer(ID_TIMER); <BR> 还有啦,在CMyWnd::PostNcDestroy() 中加入: delete this;<BR> 哎呀,腰酸背疼,眼球发涩,手背奇麻(不会吧)!不过,相信你一定会迫不及待地按下Ctrl+F5, 看着一幅幅图片在你面前轮番展示,啊,自己的屏幕保护程序!赶快赶快,换上自制的屏保,感觉就是不一样:图片任你挑,时间间隔任你改,鼠标?键盘?我想响应谁就响应谁……哎呀,谁扔的纸团:(。<BR> 其实,上面的程序还有很多可以改进的地方,比如图片总是单一地显示;bmp 文件太大,导致生成的屏幕保护程序也很大,远没有jpg合算;没有密码,没有可直接控制的界面。由于InitInstance()函数的简单处理(直接调用CMyWnd类),你会发现当你在桌面上右击,选择“属性”、“屏幕保护程序”页、“屏幕保护程序”下拉菜单、选中MyScreensaver时,MyScreensaver就直接预览了(或是直接运行了);假设你确定MyScreensaver作为你的屏幕保护程序,等你第二次进入“屏幕保护程序”页时,就直接预览。Why? 回头看看InitInstance()函数就明白了。为了让它更听话地工作,可修改InitInstance()函数:<BR> LPTSTR lpszArgv = __argv[1];<BR> if (lpszArgv[0] ==‘/’)<BR> lpszArgv++;<BR> if (lstrcmpi(lpszArgv, _T(“s”))==0)<BR> {<BR> CMyWnd* pWnd=new CMyWnd;<BR> pWnd->Create();<BR> m_pMainWnd=pWnd;<BR> return TRUE;<BR> }<BR> return FALSE;<BR> 不过现在你要是再在VC中运行这个程序,“该程序执行了非法操作,即将关闭。如果仍有问题,请与我联系(??)”将会伴随着一超重低音供你欣赏。(啊?)原因是我们加了一句return FALSE; 还有,别忘了还有一个CMyScreensaverDlg类没有用上,用它来与你的屏保直接对话再好不过了。例如,为了方便地确定时间间隔,选取图片,加上一个编辑框和几个按钮就可以了。重申一点,由于生成文件较大,占用的内存也多,如果不能运行,很可能是开的窗口太多了。这时你可以换较小的图片。
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:CDMA2000 回复日期:2002-12-16 15:35:22
<br>内容:那怎样在代码中启动*.scr文件呢?
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:bird 回复日期:2002-12-16 15:56:32
<br>内容:使用SendMessage函数向系统发送一个广播消息就可以了,具体原代码为: <BR><BR>void __fastcall TForm1::Button1Click(TObject *Sender)<BR>{<BR>SendMessage(HWND_BROADCAST,WM_SYSCOMMAND,SC_SCREENSAVE,0);<BR>} <BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -