目前的输入法可以分为两种,一种是外挂式的,一种是以dll为接口的输入法。这篇笔记讨论的主题主要是围绕外挂式的输入法的前端设计与实现。
主要解决的问题:包括位图的导出和转换,右键弹出菜单实现与功能选择,窗口的贴图,属性表的显示实现,窗口移动实现,字体选择和窗体的颜色
下面的代码是为一个简单的窗口实现,这窗口主要解决窗口移动,右键菜单,还有一些字体选择和窗口颜色变化
// 透明色.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "resource.h" #include "config.h" #include <prsht.h> #include <commctrl.h> #include <pshpack1.h> #include <crtdbg.h> #include "shellapi.h" #pragma comment (lib,"comctl32.lib") #pragma comment(lib,"shell32.lib") #define MAX_LOADSTRING 100 #pragma comment (lib,"comctl32.lib") // Global Variables: HINSTANCE hInst; HWND hInputWnd; TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); void Stand_TrackPopupMenu(HWND hWnd,WPARAM wParam, LPARAM lParam);// 右键弹出菜单 void Stand_Move(HWND hWnd,WPARAM wParam,LPARAM lParam);//窗口移动 void Stand_ONLBUTTONDOWN(HWND hWnd,WPARAM wParam,LPARAM lParam);//按钮按下的时候 void Stand_onBUTONUP(HWND hWnd,WPARAM wParam,LPARAM lParam); // int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. MSG msg; HACCEL hAccelTable; // // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MY); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = NULL; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = NULL; return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { // HWND hWnd; // hWnd=hInputWnd; hInst = hInstance; hInputWnd=CreateWindow(szWindowClass, "ds", WS_POPUP|WS_DISABLED, 500, 500, 300, 42, NULL, NULL, hInst, NULL); if (!hInputWnd) { return FALSE; } ShowWindow(hInputWnd, nCmdShow); UpdateWindow(hInputWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; TCHAR szHello[MAX_LOADSTRING]; LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); switch (message) { case WM_COMMAND: { wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch (wmId) { case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow(hWnd); break; case IDM_HELP: DoPropertySheet(hWnd); break; case IDM_WENDANG: // MessageBox(NULL,"ds","ds",MB_OK); ShellExecute(NULL, "open", "Help.chm", NULL, NULL,SW_SHOWNORMAL); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_RBUTTONDOWN: { Stand_TrackPopupMenu( hWnd,wParam, lParam);//实现右键菜单 } break; case WM_SETCURSOR: { Stand_ONLBUTTONDOWN(hWnd,wParam,lParam); } break; case WM_LBUTTONUP: { Stand_onBUTONUP(hWnd,wParam,lParam); } break; case WM_MOUSEMOVE: { Stand_Move(hWnd,wParam,lParam); } break; case WM_PAINT: { hdc=BeginPaint(hWnd,&ps); Stand_onPaint(hWnd,hdc); EndPaint(hWnd,&ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } // // 右键菜单实现 void Stand_TrackPopupMenu(HWND hWnd,WPARAM wParam, LPARAM lParam) { HMENU hMenu; HMENU hsubmenu; int cmd; hMenu=LoadMenu(hInst,MAKEINTRESOURCE(IDR_MENU1)); hsubmenu=GetSubMenu(hMenu,0); POINT pt; pt.x=LOWORD(lParam);// pt.y=HIWORD(lParam);// ClientToScreen(hWnd,&pt); cmd=TrackPopupMenu(hsubmenu,TPM_RIGHTBUTTON,pt.x,pt.y,0,hWnd,NULL); switch(cmd) { case IDM_EXIT: DestroyWindow(hWnd); break; case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_HELP: DoPropertySheet(hWnd); break; case IDM_WENDANG: ShellExecute(hWnd, "open", "Help.chm", NULL, NULL,SW_SHOWNORMAL); break; } } // //创建一个填涂区// void Stand_onPaint(HWND hWnd,HDC hdc) { HPEN hPen;//定义一支笔 HBRUSH hBrush;//创建一个画刷 char output[32]; hBrush=CreateSolidBrush(SetMyview.WndColor);//创建一个填充填充色The CreateSolidBrush function creates a logical brush that has the specified solid color SelectObject(hdc,hBrush); hPen=CreatePen(PS_SOLID,6,RGB(255,255,1));//利用这个函数创建一个RGB 是这个的的实线画笔*/ Rectangle(hdc,0,0,300,42);//画一个矩形 SelectObject(hdc,hPen); SetTextColor(hdc,SetMyview.FontColor); SelectObject(hdc,SetMyview.hfont);//选择字体种类 sprintf(output,"%s","SuCCess"); TextOut(hdc,10,10,output,strlen(output));//输出一个字先 DeleteObject(hPen); DeleteObject(hBrush); } //更新窗口,要指明那个窗口要更新 void UpdateInputWnd() { ShowWindow(hInputWnd,SW_SHOWNA); HDC hdc=GetDC(hInputWnd); Stand_onPaint(hInputWnd,hdc); ReleaseDC(hInputWnd,hdc); } // //窗口移动,捕捉鼠标/// static BOOL fMove=FALSE;//判断是否移动 static RECT inRect,drect; static SIZE sz; static POINT pwnd;// void Stand_ONLBUTTONDOWN(HWND hWnd,WPARAM wParam,LPARAM lParam) { POINT pt; HDC hdc=GetDC(hWnd); if(HIWORD(lParam)==WM_LBUTTONDOWN) { SetCapture(hWnd); //捕捉鼠标 GetCursorPos(&pt); //获得当前鼠标坐标位置 GetWindowRect(hWnd,&drect);//获得当前窗口矩形 inRect.left=drect.left; inRect.top=drect.top; inRect.right=drect.right; inRect.bottom=drect.bottom; pwnd.x=pt.x-drect.left;计算鼠标坐标与矩形左上角x坐标的距离 初始化第一个位置 pwnd.y=pt.y-drect.top;计算鼠标坐标与矩形左上角Y坐标的距离 sz.cx=inRect.right-inRect.left; sz.cy=inRect.bottom-inRect.top; fMove=TRUE; } else if (HIWORD(lParam)== WM_RBUTTONDOWN) { SetCapture(hWnd); } } //移动 void Stand_onBUTONUP(HWND hWnd,WPARAM wParam,LPARAM lParam) { POINT pt; ReleaseCapture(); if (fMove) { // MessageBox(NULL,"ds","dsd",MB_OK); GetCursorPos(&pt); MoveWindow(hWnd,pt.x-pwnd.x,pt.y-pwnd.y,sz.cx,sz.cy,TRUE);//当前位置减去之前的位置,从而得到了移动后的距离位置 } fMove=FALSE; } //计算移动窗口 void Stand_Move(HWND hWnd,WPARAM wParam,LPARAM lParam) { POINT pt; if (fMove) { GetCursorPos(&pt); drect.left = pt.x - pwnd.x; drect.top = pt.y - pwnd.y; drect.right = inRect.left + sz.cx; drect.bottom = inRect.top + sz.cy; } }
#include "StdAfx.h"
#include "config.h"
#include "resource.h"
#include "prsht.h"
#include <commctrl.h>
#include <pshpack1.h>
#include <crtdbg.h>
#include "Commdlg.h"
#pragma comment (lib,"comctl32.lib")
SetView SetMyview;
HINSTANCE hInst1;
#pragma comment (lib,"comctl32.lib")
//***************************************************//
//弹出对话框
HFONT CreateMyFont()
{
CHOOSEFONT cf;
LOGFONT lf;
HFONT hfont;
cf.lStructSize = sizeof(CHOOSEFONT);
cf.hwndOwner = (HWND)NULL;
cf.hDC = (HDC)NULL;
cf.lpLogFont = &lf;
cf.iPointSize = 0;
cf.Flags = CF_SCREENFONTS;
cf.rgbColors = RGB(0,0,0);
cf.lCustData = 0L;
cf.lpfnHook = (LPCFHOOKPROC)NULL;
cf.lpTemplateName = (LPSTR)NULL;
cf.hInstance = (HINSTANCE) NULL;
cf.lpszStyle = (LPSTR)NULL;
cf.nFontType = SCREEN_FONTTYPE;
cf.nSizeMin = 0;
cf.nSizeMax = 0;
if (ChooseFont(&cf))
{
hfont = CreateFontIndirect(cf.lpLogFont);
return (hfont);
}
else
{
return (HFONT)NULL;
}
}
//选择字体颜色,返回选择后的颜色值,这个颜色值给窗口和字体
COLORREF ChooseMyColor(HWND hWnd)
{
CHOOSECOLOR cc;
COLORREF acrCustClr[16];
DWORD rgbCurrent;
rgbCurrent=RGB(255,255,255);
ZeroMemory(&cc, sizeof(cc));
cc.lStructSize = sizeof(cc);
cc.hwndOwner = hWnd;
cc.lpCustColors = (LPDWORD) acrCustClr;
cc.rgbResult = rgbCurrent;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
if (ChooseColor(&cc)==TRUE)
{
rgbCurrent = cc.rgbResult;
}
return rgbCurrent;
}
//设置一个范围,这个是范围是用于
void InitSlider(HWND hWnd,UINT uValue)
{
SendMessage(hWnd,TBM_SETRANGE,(WPARAM)TRUE,(LPARAM)MAKELONG(0,100)); //初始化范围
SendMessage(hWnd,TBM_SETPAGESIZE,(WPARAM)TRUE,(LPARAM)5);
SendMessage(hWnd,TBM_SETPOS,(WPARAM)TRUE,(LPARAM)100);
}
BOOL WINAPI First(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_INITDIALOG:
{
HWND hSlider=GetDlgItem(hWnd,IDC_SLIDER1);
InitSlider(hSlider,100);
SetDlgItemText(hWnd,IDC_EDIT1,"100");
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
{
SetMyview.hfont=CreateMyFont();//弹出字体对话框调用系统那个
UpdateInputWnd();
}
break;
case IDC_BUTTON2:
{
SetMyview.FontColor=ChooseMyColor(hWnd);
UpdateInputWnd();
}
break;
case IDC_BUTTON3:
{
SetMyview.WndColor=ChooseMyColor(hWnd);
UpdateInputWnd();
}
break;
}
}
break;
case WM_NOTIFY:
{
switch( ((LPNMHDR)lParam)->code )
{
case NM_RELEASEDCAPTURE:
{
static char chNumBuff[20];
LONG lResult=SendMessage( ((LPNMHDR)lParam)->hwndFrom, TBM_GETPOS ,(WPARAM)0,(LPARAM)0 );
sprintf(chNumBuff,"%ld",lResult);
SetDlgItemText(hWnd,IDC_EDIT1,chNumBuff);
ShowWindow(hInputWnd,SW_SHOWNA);
//TranspanentWindow((int)lResult);
}
break;
}
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
//
BOOL WINAPI Second(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int DoPropertySheet(HWND hWnd)
{
PROPSHEETPAGE psp[2];
PROPSHEETHEADER psh;
int nRect=-1;
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[0].hInstance =hInst1;
psp[0].pszTemplate =MAKEINTRESOURCE(IDD_DIALOG1);
psp[0].pszIcon = NULL;
psp[0].pfnDlgProc = (DLGPROC)First;
psp[0].pszTitle = "常规";
psp[0].lParam = 0;
psp[0].pfnCallback = NULL;
psp[1].dwSize = sizeof(PROPSHEETPAGE);
psp[1].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[1].hInstance = hInst1;
psp[1].pszTemplate = MAKEINTRESOURCE(IDD_DIALOG2);//
psp[1].pszIcon = NULL;
psp[1].pfnDlgProc = (DLGPROC)Second;
psp[1].pszTitle ="热键";
psp[1].lParam = 0;
psp[1].pfnCallback = NULL;
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE|PSH_USEPAGELANG;
psh.hwndParent = hWnd;
psh.hInstance = hInst1;
psh.pszIcon =NULL;
psh.pszCaption = (LPSTR) "输入法后台设置";
psh.nPages = sizeof(psp)/sizeof(PROPSHEETPAGE);
psh.nStartPage = 0;
psh.ppsp = (LPCPROPSHEETPAGE) &psp;
psh.pfnCallback = NULL;
nRect=PropertySheet(&psh);
return nRect;
}
配置文件:
Config.cpp
#include "StdAfx.h"
#include "config.h"
#include "resource.h"
#include "prsht.h"
#include <commctrl.h>
#include <pshpack1.h>
#include <crtdbg.h>
#include "Commdlg.h"
#pragma comment (lib,"comctl32.lib")
SetView SetMyview;
HINSTANCE hInst1;
#pragma comment (lib,"comctl32.lib")
//***************************************************//
//弹出对话框
HFONT CreateMyFont()
{
CHOOSEFONT cf;
LOGFONT lf;
HFONT hfont;
cf.lStructSize = sizeof(CHOOSEFONT);
cf.hwndOwner = (HWND)NULL;
cf.hDC = (HDC)NULL;
cf.lpLogFont = &lf;
cf.iPointSize = 0;
cf.Flags = CF_SCREENFONTS;
cf.rgbColors = RGB(0,0,0);
cf.lCustData = 0L;
cf.lpfnHook = (LPCFHOOKPROC)NULL;
cf.lpTemplateName = (LPSTR)NULL;
cf.hInstance = (HINSTANCE) NULL;
cf.lpszStyle = (LPSTR)NULL;
cf.nFontType = SCREEN_FONTTYPE;
cf.nSizeMin = 0;
cf.nSizeMax = 0;
if (ChooseFont(&cf))
{
hfont = CreateFontIndirect(cf.lpLogFont);
return (hfont);
}
else
{
return (HFONT)NULL;
}
}
//选择字体颜色,返回选择后的颜色值,这个颜色值给窗口和字体
COLORREF ChooseMyColor(HWND hWnd)
{
CHOOSECOLOR cc;
COLORREF acrCustClr[16];
DWORD rgbCurrent;
rgbCurrent=RGB(255,255,255);
ZeroMemory(&cc, sizeof(cc));
cc.lStructSize = sizeof(cc);
cc.hwndOwner = hWnd;
cc.lpCustColors = (LPDWORD) acrCustClr;
cc.rgbResult = rgbCurrent;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
if (ChooseColor(&cc)==TRUE)
{
rgbCurrent = cc.rgbResult;
}
return rgbCurrent;
}
//设置一个范围,这个是范围是用于
void InitSlider(HWND hWnd,UINT uValue)
{
SendMessage(hWnd,TBM_SETRANGE,(WPARAM)TRUE,(LPARAM)MAKELONG(0,100)); //初始化范围
SendMessage(hWnd,TBM_SETPAGESIZE,(WPARAM)TRUE,(LPARAM)5);
SendMessage(hWnd,TBM_SETPOS,(WPARAM)TRUE,(LPARAM)100);
}
BOOL WINAPI First(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_INITDIALOG:
{
HWND hSlider=GetDlgItem(hWnd,IDC_SLIDER1);
InitSlider(hSlider,100);
SetDlgItemText(hWnd,IDC_EDIT1,"100");
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
{
SetMyview.hfont=CreateMyFont();//弹出字体对话框调用系统那个
UpdateInputWnd();
}
break;
case IDC_BUTTON2:
{
SetMyview.FontColor=ChooseMyColor(hWnd);
UpdateInputWnd();
}
break;
case IDC_BUTTON3:
{
SetMyview.WndColor=ChooseMyColor(hWnd);
UpdateInputWnd();
}
break;
}
}
break;
case WM_NOTIFY:
{
switch( ((LPNMHDR)lParam)->code )
{
case NM_RELEASEDCAPTURE:
{
static char chNumBuff[20];
LONG lResult=SendMessage( ((LPNMHDR)lParam)->hwndFrom, TBM_GETPOS ,(WPARAM)0,(LPARAM)0 );
sprintf(chNumBuff,"%ld",lResult);
SetDlgItemText(hWnd,IDC_EDIT1,chNumBuff);
ShowWindow(hInputWnd,SW_SHOWNA);
//TranspanentWindow((int)lResult);
}
break;
}
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
//
BOOL WINAPI Second(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int DoPropertySheet(HWND hWnd)
{
PROPSHEETPAGE psp[2];
PROPSHEETHEADER psh;
int nRect=-1;
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[0].hInstance =hInst1;
psp[0].pszTemplate =MAKEINTRESOURCE(IDD_DIALOG1);
psp[0].pszIcon = NULL;
psp[0].pfnDlgProc = (DLGPROC)First;
psp[0].pszTitle = "常规";
psp[0].lParam = 0;
psp[0].pfnCallback = NULL;
psp[1].dwSize = sizeof(PROPSHEETPAGE);
psp[1].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[1].hInstance = hInst1;
psp[1].pszTemplate = MAKEINTRESOURCE(IDD_DIALOG2);//
psp[1].pszIcon = NULL;
psp[1].pfnDlgProc = (DLGPROC)Second;
psp[1].pszTitle ="热键";
psp[1].lParam = 0;
psp[1].pfnCallback = NULL;
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE|PSH_USEPAGELANG;
psh.hwndParent = hWnd;
psh.hInstance = hInst1;
psh.pszIcon =NULL;
psh.pszCaption = (LPSTR) "输入法后台设置";
psh.nPages = sizeof(psp)/sizeof(PROPSHEETPAGE);
psh.nStartPage = 0;
psh.ppsp = (LPCPROPSHEETPAGE) &psp;
psh.pfnCallback = NULL;
nRect=PropertySheet(&psh);
return nRect;
}
config.h
#pragma once
#define WIN32_LEAN_AND_MEAN
#include "StdAfx.h"
#include "prsht.h"
#include <commctrl.h>
#include <pshpack1.h>
#include <crtdbg.h>
#pragma comment (lib,"comctl32.lib")
HFONT CreateMyFont();//创建我的字体
int DoPropertySheet(HWND hWnd);
BOOL WINAPI First(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam);
BOOL WINAPI Second(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam);
//定义个结构体这个结构是用于设置字体的颜色,字体大小,窗口的背景颜色
typedef struct _tagSetView
{
HFONT hfont;//选择字体
COLORREF FontColor;//字体颜色
COLORREF WndColor;//窗口颜色
BOOL SetSkin;//设置皮肤
}
SetView;
extern SetView SetMyview;
extern HWND hInputWnd;
extern HINSTANCE hInst1;
void UpdateInputWnd();//更新窗口
void Stand_onPaint(HWND hWnd,HDC hdc);//输出窗口的颜色值