我很久以前寫的一篇文章,現在轉移到這裏。
前天突發靈感認爲如果能做一個在手機桌面上的每日問候程序一定會很有意思,於是開始了Pocket PC 今日插件(today plugin)編程的學習和研究。
受 怪博士與機器娃娃中阿拉蕾的形象的影響,打算做一個“我的小雨”---在我的手機桌面上運行每日提醒程序,比如讓她在當時間滿足某個條件的時候發出事先設 定好的聲音,顯示特定的文字等,顯示的文字可以是名言,笑話,英文經典句子(如果還要考六級)等,只要是能想到的都是可以做出來的。
顯示的內容和規律我可以設計一種簡單語言來描述,這樣我可以把提示內容放在我網站上動態更新和管理,程序作爲客戶端能自動或手動從我網站下載這些文本內容和規則描述,達到動態提示的目的,而且這個程序以後發佈了肯定可以給很多人帶來快樂。
如果有精力的話,我還想把以前學的人工智能知識運用進來,讓她能跟主人互動,慢慢的能瞭解主人的性格,知道主人的喜好,從而顯示不同的內容等,不過這樣貌似越來越複雜了。暫且擱着,把簡單的做好了以後再改進吧。。。
先去網上搜集資料,瞭解開發的步驟,看過的有這幾篇文章:
首先是微軟官方的廣播,裏面有一個視頻教程(附帶pdf),看完感覺很有用:
大郭的塗鴉 的博客上的一篇文章講了基於.net開發今日插件,不過貌似.net開發的插進運行速度太慢,畢竟手機上資源有限嘛:
http://guowee.javaeye.com/blog/397382
還看了其他一些博客不過都沒啥幫助,在google上到國外網站找到很好的一篇:
http://www.codeproject.com/KB/mobile/CTodayWindow.aspx
這個要註冊,但是文章很詳細,還有源代碼供下載研究,值得。
看完這些資料,知道了今日插件是手機的shell.exe調用一個dll實現的,dll必須要導出InitializeCustomItem @240
,平時熟悉的今日的插件列表原來與手機的註冊表裏面today下的項一一對應。使用遠程註冊表編輯器試着做了幾個小測試,插件的原理基本搞懂了。
再認真研究了一下那個源代碼,差不多了,開始做我的插件。
首先蒐集素材,在網上找到一些阿拉蕾的大頭貼和卡通玩具照片,用ps裁一下, 在visual studio裏面做了幾個icon。另外留了幾張圖片做應用程序背景。
用 vs2008創建一個智能設備DLL項目MyToday,根據mytoday 的源代碼(也是國外的網站上找到的,它用CTodayWindow封裝了dll必須要乾的事,是別人用eVC編譯的項目,我單獨把文件複製到2008也能 編譯),直接在它的基礎上修改要方便一些。
前面的幾個文件如下:(各個文件用等號線分割開)
=====================================================================
// stdafx.h : 標準系統包含文件的包含文件,
// 或是經常使用但不常更改的
// 特定於項目的包含文件
//
#pragma once
#pragma comment(linker, "/nodefaultlib:libc.lib")
#pragma comment(linker, "/nodefaultlib:libcd.lib")
// 注意 - 這個值與作爲目標的 Windows CE OS 版本的關聯性並不強
#define WINVER _WIN32_WCE
#include <ceconfig.h>
#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
#define SHELL_AYGSHELL
#endif
#ifdef _CE_DCOM
#define _ATL_APARTMENT_THREADED
#endif
#include <windows.h>
#include <commctrl.h>
#include <aygshell.h>
#pragma comment(lib, "aygshell.lib")
// Windows 頭文件:
#include <windows.h>
#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
#ifndef _DEVICE_RESOLUTION_AWARE
#define _DEVICE_RESOLUTION_AWARE
#endif
#endif
#ifdef _DEVICE_RESOLUTION_AWARE
#include "DeviceResolutionAware.h"
#endif
#if _WIN32_WCE < 0x500 && ( defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP) )
#pragma comment(lib, "ccrtrtti.lib")
#ifdef _X86_
#if defined(_DEBUG)
#pragma comment(lib, "libcmtx86d.lib")
#else
#pragma comment(lib, "libcmtx86.lib")
#endif
#endif
#endif
#include <altcecrt.h>
// TODO: 在此處引用程序需要的其他頭文件
=====================================================================
// stdafx.cpp : 只包括標準包含文件的源文件
// MyToday.pch 將作爲預編譯頭
// stdafx.obj 將包含預編譯類型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中
// 引用任何所需的附加頭文件,而不是在此文件中引用
=====================================================================
// TodayWindow.h: interface for the CTodayWindow class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_TODAYWINDOW_H__50D4F5EE_C442_4756_8D0B_7FFBACF0AC2C__INCLUDED_)
#define AFX_TODAYWINDOW_H__50D4F5EE_C442_4756_8D0B_7FFBACF0AC2C__INCLUDED_
#include <windows.h>
#include <todaycmn.h>
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CTodayWindow
{
public:
// Member Variables
HWND m_hWnd;
// Methods
CTodayWindow();
CTodayWindow(HINSTANCE hInstance, LPCTSTR lpszClassName, LPCTSTR lpszWindowName);
virtual ~CTodayWindow();
// Main Create method
BOOL Create(HWND hWndParent, DWORD dwStyle = WS_VISIBLE | WS_CHILD);
// Update Window
void RefreshWindow(BOOL bShow = FALSE);
// Set Methods
BOOL SetIcon(UINT uID, int xDrawAt = 2, int yDrawAt = 0);
void SetItemHeight(int nHeight);
void SetClassInfo(LPCTSTR lpszClassName, LPCTSTR lpszWindowName);
void SetInstance(HINSTANCE hInstance);
// Get Methods
HWND GetParent() {return m_hParentHwnd;};
int GetItemHeight() {return m_nHeight;};
HINSTANCE GetInstance() {return m_hInstance;};
HICON GetIcon() {return m_hIcon;};
LPCTSTR GetClassName() {return m_lpszClassName;};
LPCTSTR GetWindowName() {return m_lpszWindowName;};
// Register/Unregister TodayWindow
void RegisterTodayClass(WNDPROC wndProc);
void UnregisterTodayClass();
// TodayWndProc - main message loop
virtual LRESULT CALLBACK TodayWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
BOOL m_bInitialRefresh;
int m_nHeight;
POINT m_pointIconPos;
HWND m_hParentHwnd;
HICON m_hIcon;
HINSTANCE m_hInstance;
LPCTSTR m_lpszClassName;
LPCTSTR m_lpszWindowName;
COLORREF m_crTodayText;
HFONT m_hNormalTodayFont;
HFONT m_hBoldTodayFont;
virtual void DrawTodayIcon(HDC hDC, int xPos, int yPos);
virtual void GetTodayDefaults();
// Message handlers
virtual int OnCreate(LPCREATESTRUCT lpCreateStruct);
virtual void OnDestroy();
virtual void OnPaint(HDC hDC);
virtual void OnEraseBkgnd(HDC hDC);
virtual void OnTodayCustomQueryRefreshCache(TODAYLISTITEM *pTodayListItem, BOOL *pResult);
virtual BOOL OnTodayCustomClearCache(TODAYLISTITEM *pTodayListItem);
virtual void OnLButtonUp(UINT nFlags, POINT point);
virtual void OnLButtonDown(UINT nFlags, POINT point);
virtual void OnSettingChange(UINT nFlags, LPCTSTR lpszSection);
virtual LRESULT OnNotify(UINT nID, NMHDR* pNMHDR);
virtual LRESULT OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
};
#endif // !defined(AFX_TODAYWINDOW_H__50D4F5EE_C442_4756_8D0B_7FFBACF0AC2C__INCLUDED_)
=====================================================================
// TodayWindow.cpp: implementation of the CTodayWindow class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TodayWindow.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CTodayWindow::CTodayWindow()
{
m_hWnd = NULL;
}
CTodayWindow::CTodayWindow(HINSTANCE hInstance, LPCTSTR lpszClassName, LPCTSTR lpszWindowName)
{
m_lpszClassName = lpszClassName;
m_lpszWindowName = lpszWindowName;
m_hInstance = hInstance;
CTodayWindow();
}
CTodayWindow::~CTodayWindow()
{
if (m_hIcon)
DestroyIcon(m_hIcon);
if (m_hNormalTodayFont)
DeleteObject(m_hNormalTodayFont);
if (m_hBoldTodayFont)
DeleteObject(m_hBoldTodayFont);
}
//////////////////////////////////////////////////////////////////////
// Create TodayWindow with given parent and style
//////////////////////////////////////////////////////////////////////
BOOL CTodayWindow::Create(HWND hWndParent, DWORD dwStyle)
{
m_bInitialRefresh = TRUE;
m_hParentHwnd = hWndParent;
m_hWnd = CreateWindow(m_lpszClassName, m_lpszWindowName, dwStyle, 0, 0, GetSystemMetrics(SM_CXSCREEN), 0, m_hParentHwnd, NULL, m_hInstance, NULL);
// Get default today attributes
GetTodayDefaults();
return (m_hWnd != NULL);
}
//////////////////////////////////////////////////////////////////////
// Register/Unregister TodayWindowClass
//////////////////////////////////////////////////////////////////////
void CTodayWindow::RegisterTodayClass(WNDPROC wndProc)
{
WNDCLASS wndClass;
memset(&wndClass, 0, sizeof(wndClass));
wndClass.hCursor = 0;
wndClass.hIcon = 0;
wndClass.hInstance = m_hInstance;
wndClass.lpszClassName = m_lpszClassName;
wndClass.lpszMenuName = NULL;
wndClass.style = CS_VREDRAW | CS_HREDRAW;
wndClass.hbrBackground = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
wndClass.lpfnWndProc = wndProc;
RegisterClass(&wndClass);
}
void CTodayWindow::UnregisterTodayClass()
{
if (m_hInstance)
UnregisterClass(m_lpszClassName, m_hInstance);
}
//////////////////////////////////////////////////////////////////////
// Set Methods
//////////////////////////////////////////////////////////////////////
BOOL CTodayWindow::SetIcon(UINT uID, int xDrawAt, int yDrawAt)
{
if (m_hIcon)
{
DestroyIcon(m_hIcon);
m_hIcon = NULL;
}
if (m_hInstance)
{
m_hIcon = (HICON)LoadImage(m_hInstance, MAKEINTRESOURCE(uID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
m_pointIconPos.x = xDrawAt;
m_pointIconPos.y = yDrawAt;
}
return (m_hIcon != NULL);
}
void CTodayWindow::SetItemHeight(int nHeight)
{
m_nHeight = nHeight;
}
void CTodayWindow::SetClassInfo(LPCTSTR lpszClassName, LPCTSTR lpszWindowName)
{
m_lpszClassName = lpszClassName;
m_lpszWindowName = lpszWindowName;
}
void CTodayWindow::SetInstance(HINSTANCE hInstance)
{
m_hInstance = hInstance;
}
void CTodayWindow::RefreshWindow(BOOL bShow)
{
if (m_hWnd)
{
if (bShow)
ShowWindow(m_hWnd, SW_SHOWNORMAL);
UpdateWindow(m_hWnd);
}
}
//////////////////////////////////////////////////////////////////////
// Main WndProc
//////////////////////////////////////////////////////////////////////
LRESULT CTodayWindow::TodayWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE :
{
LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
if (OnCreate(lpcs) == -1)
return -1;
break;
}
case WM_DESTROY :
{
OnDestroy();
return 0;
}
case WM_PAINT :
{
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(m_hWnd, &ps);
DrawTodayIcon(hDC, 2, 2);
OnPaint(hDC);
EndPaint(m_hWnd, &ps);
break;
}
case WM_ERASEBKGND :
{
HDC hDC = (HDC)wParam;
OnEraseBkgnd(hDC);
return TRUE;
}
case WM_TODAYCUSTOM_CLEARCACHE :
{
TODAYLISTITEM *ptli = (TODAYLISTITEM *)wParam;
return (LRESULT)OnTodayCustomClearCache(ptli);
}
case WM_TODAYCUSTOM_QUERYREFRESHCACHE :
{
BOOL bResult = FALSE;
TODAYLISTITEM *ptli = (TODAYLISTITEM *)wParam;
if (m_bInitialRefresh)
{
ptli->cyp = m_nHeight;
m_bInitialRefresh = FALSE;
bResult = TRUE;
}
OnTodayCustomQueryRefreshCache(ptli, &bResult);
return (LRESULT)bResult;
}
case WM_LBUTTONDOWN :
{
POINT point;
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
OnLButtonDown(wParam, point);
return 0;
}
case WM_LBUTTONUP :
{
POINT point;
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
OnLButtonUp(wParam, point);
return 0;
}
case WM_SETTINGCHANGE :
{
OnSettingChange(wParam, (LPCTSTR)lParam);
return 0;
}
case WM_NOTIFY :
{
NMHDR* pNMHDR = (NMHDR*)lParam;
return OnNotify(wParam, pNMHDR);
}
default :
return OnMessage(uMsg, wParam, lParam);
}
return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
}
//////////////////////////////////////////////////////////////////////
// Virtual message handlers - these are predefined and overridable
//////////////////////////////////////////////////////////////////////
int CTodayWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
return 0;
}
void CTodayWindow::OnDestroy()
{
}
void CTodayWindow::OnPaint(HDC hDC)
{
}
void CTodayWindow::OnEraseBkgnd(HDC hDC)
{
TODAYDRAWWATERMARKINFO dwi;
dwi.hdc = hDC;
GetClientRect(m_hWnd, &dwi.rc);
dwi.hwnd = m_hWnd;
SendMessage(m_hParentHwnd, TODAYM_DRAWWATERMARK, 0,(LPARAM)&dwi);
}
void CTodayWindow::OnLButtonUp(UINT nFlags, POINT point)
{
}
void CTodayWindow::OnLButtonDown(UINT nFlags, POINT point)
{
}
void CTodayWindow::OnTodayCustomQueryRefreshCache(TODAYLISTITEM *pTodayListItem, BOOL *bResult)
{
}
BOOL CTodayWindow::OnTodayCustomClearCache(TODAYLISTITEM *pTodayListItem)
{
return FALSE;
}
void CTodayWindow::OnSettingChange(UINT nFlags, LPCTSTR lpszSection)
{
}
LRESULT CTodayWindow::OnNotify(UINT nID, NMHDR* pNMHDR)
{
return 0;
}
LRESULT CTodayWindow::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
}
// Other protected virtual methods
void CTodayWindow::DrawTodayIcon(HDC hDC, int xPos, int yPos)
{
if (m_hIcon)
{
SetBkMode(hDC, TRANSPARENT);
::DrawIcon(hDC, m_pointIconPos.x, m_pointIconPos.y, m_hIcon);
}
}
void CTodayWindow::GetTodayDefaults()
{
LOGFONT lf;
HFONT hSysFont;
// Default today item font color
m_crTodayText = SendMessage(m_hParentHwnd, TODAYM_GETCOLOR, (WPARAM)TODAYCOLOR_TEXT, NULL);
// Default today fonts
hSysFont = (HFONT)GetStockObject(SYSTEM_FONT);
GetObject(hSysFont, sizeof(LOGFONT), &lf);
_tcscpy(lf.lfFaceName, _T("Tahoma"));
lf.lfHeight = -11;
// Normal text
lf.lfWeight = FW_NORMAL;
m_hNormalTodayFont = CreateFontIndirect(&lf);
// Bold text
lf.lfWeight = FW_BOLD;
m_hBoldTodayFont = CreateFontIndirect(&lf);
}
=====================================================================
除了這些之外,還需要一個resource.h,和一個資源文件,裏面就是些圖標,很簡單,自己動手建了。
上面的幾個文件有點類似MFC把插件通常要做的事都寫到一個類裏,把可能會不同的處理函數寫成虛函數供子類重載。
下面的CMyToday類則繼承上面的類,在相應的消息處理函數裏做一些我要的動作。
=====================================================================
// MyToday.h: interface for the CMyToday class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_MYTODAY_H__61C9A8EE_BCAC_4AB3_B2FC_57811B4C153B__INCLUDED_)
#define AFX_MYTODAY_H__61C9A8EE_BCAC_4AB3_B2FC_57811B4C153B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "TodayWindow.h"
class CMyToday : public CTodayWindow
{
public :
CMyToday(HINSTANCE hInstance, LPCTSTR lpszClassName, LPCTSTR lpszWindowName);
virtual ~CMyToday();
protected :
HICON m_hPowerIcon;
virtual void OnLButtonUp(UINT nFlags, POINT point);
virtual void OnPaint(HDC hDC);
};
#endif // !defined(AFX_MYTODAY_H__61C9A8EE_BCAC_4AB3_B2FC_57811B4C153B__INCLUDED_)
=====================================================================
// MyToday.cpp : 定義 DLL 應用程序的入口點。
//
#include "stdafx.h"
//下面這個函數是系統自動生成,在這裏先註釋了,後面會有實現
//BOOL APIENTRY DllMain( HANDLE hModule,
// DWORD ul_reason_for_call,
// LPVOID lpReserved
// )
//{
// return TRUE;
//}
//
// MyToday.cpp: implementation of the CMyToday class.
//
//////////////////////////////////////////////////////////////////////
#include "resource.h"
#include "MyToday.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMyToday::CMyToday(HINSTANCE hInstance, LPCTSTR lpszClassName, LPCTSTR lpszWindowName)
: CTodayWindow(hInstance, lpszClassName, lpszWindowName)
{
m_hPowerIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_POWER_ICON));
}
CMyToday::~CMyToday()
{
if (m_hPowerIcon)
DestroyIcon(m_hPowerIcon);
CTodayWindow::~CTodayWindow();
}
//////////////////////////////////////////////////////////////////////
// Message handlers
//////////////////////////////////////////////////////////////////////
void CMyToday::OnLButtonUp(UINT nFlags, POINT point)
{
RECT rect;
rect.left = 200;
rect.top = 2;
rect.right = rect.left + 32;
rect.bottom = rect.top + 32;
if (PtInRect(&rect, point))
{
// Click on power icon runs Power control panel applet
PROCESS_INFORMATION pi;
::CreateProcess(_T("//Program Files//我的小雨//我的小雨.exe"), _T("cplmain.cpl,3"), NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
}
else
MessageBox(NULL, _T("我喝水只喝純淨水,牛奶只喝純牛奶,所以我很單純."), _T("冰玉之魂的自白"), MB_OK | MB_ICONINFORMATION);
}
void CMyToday::OnPaint(HDC hDC)
{
HFONT hFontOld;
RECT rect;
SIZE size;
SetTextColor(hDC, m_crTodayText);
// First draw text using bold today font
LPCTSTR szText = _T("吳勝蘭的小雨 怪博士的阿拉蕾");
hFontOld = (HFONT)SelectObject(hDC, m_hBoldTodayFont);
GetTextExtentPoint32(hDC, szText, _tcslen(szText), &size);
rect.left = 30;
rect.top = 0;
rect.right = rect.left + size.cx;
rect.bottom = size.cy;
DrawText(hDC, szText, -1, &rect, DT_LEFT);
// Then draw text using normal today font
szText = _T("小雨:博士今天心情好嗎?/n我:恩,蠻好的!");
SelectObject(hDC, m_hNormalTodayFont);
GetTextExtentPoint32(hDC, szText, _tcslen(szText), &size);
rect.left = 30;
rect.top = 15;
rect.right = rect.left + size.cx;
rect.bottom = rect.top + size.cy;
DrawText(hDC, szText, -1, &rect, DT_LEFT);
SelectObject(hDC, hFontOld);
if (m_hPowerIcon)
{
SetBkMode(hDC, TRANSPARENT);
DrawIcon(hDC, 200, 2, m_hPowerIcon);
}
}
=====================================================================
//最後,這是test.h文件,聲明插件dll需要實現的函數
#include "MyToday.h"
#include "resource.h"
HWND APIENTRY InitializeCustomItem(TODAYLISTITEM *ptli, HWND hWndParent);
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
=====================================================================
//這是test.cpp文件,非常簡單明瞭
#include "stdafx.h"
#include "Test.h"
static CMyToday* myToday;
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH :
myToday = new CMyToday((HINSTANCE)hModule, _T("MyTodayClass"), _T("MyTodayWnd"));
myToday->SetItemHeight(40);
myToday->SetIcon(IDI_APP_ICON);
myToday->UnregisterTodayClass();
break;
case DLL_PROCESS_DETACH :
delete myToday;
break;
}
return TRUE;
}
HWND InitializeCustomItem(TODAYLISTITEM *ptli, HWND hWndParent)
{
myToday->RegisterTodayClass((WNDPROC)WndProc);
myToday->Create(hWndParent, WS_VISIBLE | WS_CHILD);
myToday->RefreshWindow(TRUE);
return myToday->m_hWnd;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return myToday->TodayWndProc(uMsg, wParam, lParam);
}
====================================================================
最後編譯dll的時候link命令選項要加一個 /def MyToday.def
MyToday.def 文件上面給了,就是放函數導出的信息
源 代碼到這裏就都列完了,經過調試都是沒有問題的(若中文有問題,可將項目屬性字符集選擇未設置)。用usb連接電腦和手機,在vs2008裏面選擇 debug, 平臺選擇智能設備(注意不是模擬器,前面有CHS的是模擬器,選最後一個Windows Mobile 5.0 Pocket PC SDK (ARMV4I))。點調試,系統會自動將程序編譯好,並將DLL複製到手機上,由於dll不是可執行的,所以後面會彈出錯誤提示,沒關係。
先 改插件註冊表,用Visual Studio Remote Registry Editor (在開始菜單裏vs2008目錄下)連接到手機,定位到[HKEY_LOCAL_MACHINE/Software/Microsoft/Today /Items],我在這裏就不再建新插件項了,懶人自有懶法,直接改了手機鬧鐘插件pTravelAlarm,只需把dll建的值改爲/Program Files/MyToday/MyToday.dll 即可,/表示機身內存的根目錄,MyToday.dll 是vs自動部署進去的。
打開手機開始菜單->設置->今日->項目, 找到剛纔那個插件名字,啓用他,OK退出
回到桌面上後,可以看到激動人心的嶄新的插件:
觸擊屏幕上的文字,彈出這個:
點擊小雨的頭像,彈出如下動畫(動畫是用C#寫的另外一個程序):
在CMyToday類裏有這樣一行代碼
::CreateProcess(_T("//Program Files//我的小雨//我的小雨.exe"), _T("cplmain.cpl,3"), NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
實際上是調用我用C#寫的我的小雨.exe, 這個程序其實很簡單,就是交替顯示兩張圖片3次,來表示搖頭,出場的水平運動也是用timer來實現的,部分代碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace 我的小雨
{
public partial class Form1 : Form
{
private int count = 0;
private int x1=-30;
private int x2=80;
private double t = 0;
private int limit = 100;
private double limitLog;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
initialComponents();
araleShowHappy(500, 3);
limitLog = Math.Log(limit);
}
private void araleShowHappy(int speed, int times)
{
count = times;
timer1.Interval = speed;
timer1.Enabled = true;
}
private void initialComponents()
{
pictureBox2.Left = -30;
pictureBox2.Top = 0;
pictureBox3.Left = -30;
pictureBox3.Top = 0;
}
private void menuItem5_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void pictureBox3_Click(object sender, EventArgs e)
{
araleShowHappy(300, 2);
}
private void timer1_Tick(object sender, EventArgs e)
{
if (pictureBox3.Visible)
{
pictureBox3.Visible = false;
}
else
{
pictureBox3.Visible = true;
count--;
if (0 == count)
{
timer1.Enabled = false;
}
}
}
private void timer2_Tick(object sender, EventArgs e)
{
if (t<limit)
{
t += 1 ;
int temp = Convert.ToInt32(Math.Log(t) / limitLog * (x2 - x1));
pictureBox2.Left = x1 + temp;
pictureBox3.Left = x1 + temp;
}
else
{
timer2.Enabled = false;
pictureBox4.Visible = true;
}
}
private void pictureBox4_Click(object sender, EventArgs e)
{
araleShowHappy(150, 3);
}
}
}
show一下界面設計:
今日插件開發初探就這些了,得做作業了,研究先告一段落,敬請期待後續成果吧!
附一個怪博士與機器娃娃的介紹,免得大家吐口水說我弱智,呵呵:
阿 拉蕾日本漫畫大師鳥山明1979年作品。和他製造的機器娃娃阿拉蕾的一系列故事。 阿拉蕾小檔案: 英文名:Alrale 全名:則卷阿拉蕾 性別:女 屬性:則卷千兵衛博士製造的機器娃娃 年齡:從外表看是初中生 學校:企鵝村村立中學 一個愛闖禍的機器女孩,一堆亂七八糟的故事,嘲笑了幾乎所有當時日本流行的卡通人物:永遠也幫不上忙的愛吃話梅的超人;鹹蛋超人只是畫面的補白;日本的名 產--怪獸與人類共同居住還一起玩耍。這是鳥山明獨特的幽默,在這部作品裏他開始嘗試創造一個所有的生物共存平等的世界--企鵝村。這個世界延續在他以後 的作品中,並在《龍珠》裏達到了巔峯。那麼,爲什麼要選阿拉蕾呢?她既不是當時流行的格鬥型也明顯不是美少女,只是個缺根筋的秀逗機器人,說到機器人,當 時的確也有科幻類的漫畫,藤子不二雄的《機器貓》就是。但《阿拉蕾》的主題又明顯不僅僅是歌頌科學發明,甚至有時它還表現出對工業時代的嘲諷和反感:與代 表自然生存狀態的企鵝村相對--大都會島的生活就象我們日常生活的城市一樣:華麗、忙碌、充斥着拘束與規則。而阿拉蕾只是在不斷的感慨"到底是城裏呀"並 將之破壞的亂七八糟之後,興高采烈的回到了企鵝島。阿拉蕾可以說是一個自然人的形象(其實《龍珠》裏的悟空也是,可見鳥山明對自然人情有獨鍾)--所謂自 然人是法國哲學家盧梭在《美育通信》裏提出的,既指在自然的環境、人際關係中成長起來的的淳樸的人。在《阿》裏只有全無機心的阿拉蕾才能夠天下無敵,大概 是反映了作者認爲自然人的狀態纔是最完美的境界。所以,在讀《阿》時,我們常常會有回到童年的感覺,大概就是這個原因吧。