Windows Mobile智能手机今日插件编程开发初探(使用C++, vs2008, Pocket PC 5.0内核)

来源:互联网 发布:mac修改u盘格式 编辑:程序博客网 时间:2024/05/16 04:58

我很久以前写的一篇文章,现在转移到这里。

 

前天突发灵感认为如果能做一个在手机桌面上的每日问候程序一定会很有意思,于是开始了Pocket PC 今日插件(today plugin)编程的学习和研究。

受 怪博士与机器娃娃中阿拉蕾的形象的影响,打算做一个“我的小雨”---在我的手机桌面上运行每日提醒程序,比如让她在当时间满足某个条件的时候发出事先设 定好的声音,显示特定的文字等,显示的文字可以是名言,笑话,英文经典句子(如果还要考六级)等,只要是能想到的都是可以做出来的。

显示的内容和规律我可以设计一种简单语言来描述,这样我可以把提示内容放在我网站上动态更新和管理,程序作为客户端能自动或手动从我网站下载这些文本内容和规则描述,达到动态提示的目的,而且这个程序以后发布了肯定可以给很多人带来快乐。

如果有精力的话,我还想把以前学的人工智能知识运用进来,让她能跟主人互动,慢慢的能了解主人的性格,知道主人的喜好,从而显示不同的内容等,不过这样貌似越来越复杂了。暂且搁着,把简单的做好了以后再改进吧。。。

先去网上搜集资料,了解开发的步骤,看过的有这几篇文章:

首先是微软官方的广播,里面有一个视频教程(附带pdf),看完感觉很有用:

http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032328426&EventCategory=3&culture=zh-CN&CountryCode=CN

大郭的涂鸦 的博客上的一篇文章讲了基于.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自动部署进去的。

image

打开手机开始菜单->设置->今日->项目, 找到刚才那个插件名字,启用他,OK退出

Screen002

回到桌面上后,可以看到激动人心的崭新的插件:

Screen003

触击屏幕上的文字,弹出这个:

Screen004

点击小雨的头像,弹出如下动画(动画是用C#写的另外一个程序):

Screen005  Screen007 Screen008

在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一下界面设计:

image

 

今日插件开发初探就这些了,得做作业了,研究先告一段落,敬请期待后续成果吧!

 

附一个怪博士与机器娃娃的介绍,免得大家吐口水说我弱智,呵呵:

阿 拉蕾日本漫画大师鸟山明1979年作品。和他制造的机器娃娃阿拉蕾的一系列故事。 阿拉蕾小档案: 英文名:Alrale 全名:则卷阿拉蕾 性别:女 属性:则卷千兵卫博士制造的机器娃娃 年龄:从外表看是初中生 学校:企鹅村村立中学 一个爱闯祸的机器女孩,一堆乱七八糟的故事,嘲笑了几乎所有当时日本流行的卡通人物:永远也帮不上忙的爱吃话梅的超人;咸蛋超人只是画面的补白;日本的名 产--怪兽与人类共同居住还一起玩耍。这是鸟山明独特的幽默,在这部作品里他开始尝试创造一个所有的生物共存平等的世界--企鹅村。这个世界延续在他以后 的作品中,并在《龙珠》里达到了巅峰。那么,为什么要选阿拉蕾呢?她既不是当时流行的格斗型也明显不是美少女,只是个缺根筋的秀逗机器人,说到机器人,当 时的确也有科幻类的漫画,藤子不二雄的《机器猫》就是。但《阿拉蕾》的主题又明显不仅仅是歌颂科学发明,甚至有时它还表现出对工业时代的嘲讽和反感:与代 表自然生存状态的企鹅村相对--大都会岛的生活就象我们日常生活的城市一样:华丽、忙碌、充斥着拘束与规则。而阿拉蕾只是在不断的感慨"到底是城里呀"并 将之破坏的乱七八糟之后,兴高采烈的回到了企鹅岛。阿拉蕾可以说是一个自然人的形象(其实《龙珠》里的悟空也是,可见鸟山明对自然人情有独钟)--所谓自 然人是法国哲学家卢梭在《美育通信》里提出的,既指在自然的环境、人际关系中成长起来的的淳朴的人。在《阿》里只有全无机心的阿拉蕾才能够天下无敌,大概 是反映了作者认为自然人的状态才是最完美的境界。所以,在读《阿》时,我们常常会有回到童年的感觉,大概就是这个原因吧。