今年6月中旬,我曾经基于MFC写过一个WiFiHelper的小程序,开启和关闭虚拟WiFi,并且能够支持定时关机,当然,真正使用虚拟WiFi还需要手动设置共享。并且,由于我的是台式机,所以并没有去升级WiFiHelper。
估计是即将毕业的缘故,总想做出一些比较有意思的软件,让人看到我的水平,也就不停的Coding,每次给我妈打电话,也就是说在写代码,事实上,也是经常在写代码。
最开始写WiFiHelper 的时候,纯粹是为了帮助朋友们简便的开启和关闭WiFi,笔记本开启了WiFi,如果关机了,那么肯定就没有WiFi了,但是一直开着,笔记本也得休息一下不是,很多人使用计算机,只会简单的玩游戏登QQ,不要高估用户的操作能力,想想看Linux确实高估了。所以,很多人都不会使用shutdown设置定时关机,于是我便在WiFiHelper中添加了定时关机的功能,反正加起来都是支持封装命令(netsh shutdown),并使用管道获取信息输出。
9月份,那个时候Windows8.1出来了,很多人开始装8.1,我就决定写一个USB启动盘制作工具;以前发表过Blog:如何开发一款USB启动盘制作工具 被OSChina推荐过,那次写代码的经历让我学会了Win32 API的窗口编程的流程和细节,最早完全掌握Win32编程是利用超类化修改了Edit控件,因为默认的记事本的菜单不太习惯,所以就自己超了下,子类化因为没掌握好就没有使用。
2
|
ZeroMemory(&PreEditEx, sizeof (PreEditEx));
|
3
|
PreEditEx.cbSize= sizeof (WNDCLASSEX);
|
4
|
GetClassInfoEx(0,L "EDIT" ,&PreEditEx);
|
5
|
OldEditWndProc=PreEditEx.lpfnWndProc;
|
6
|
PreEditEx.lpfnWndProc=PreEditExWndProc;
|
7
|
//PreEditEx.lpszMenuName=
|
8
|
PreEditEx.lpszClassName=L "PreEditControl" ;
|
9
|
RegisterClassEx(&PreEditEx);
|
OldEditWndProc是函数指针,用来保留老的窗口处理函数
1
|
LRESULT (CALLBACK* OldEditWndProc)( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
最后就是自己写窗口函数
001
|
LRESULT CALLBACK PreEditExWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
027
|
mId = LOWORD(wParam);
|
028
|
mEvent = HIWORD(wParam);
|
032
|
SendMessage(hWnd,EM_UNDO,0,0L);
|
035
|
SendMessage(hWnd,WM_COPY,0,0L);
|
038
|
SendMessage(hWnd,WM_PASTE,0,0L);
|
041
|
SendMessage(hWnd,WM_CUT,0,0L);
|
043
|
case IDM_EDIT_SELECTALL:
|
044
|
SendMessage(hWnd, EM_SETSEL, 0, -1);
|
045
|
SendMessage(hWnd,EM_SCROLLCARET,0,0L);
|
049
|
SendMessage(hWnd,WM_CLEAR,0,0L);
|
052
|
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_SETBOX), hWnd, OpenOpDlg);
|
056
|
MessageBox(NULL,L "Alt+F2 is Update" ,L "Alt+F2" ,MB_OK);
|
062
|
SetWindowText(hWnd,L "" );
|
063
|
//WCHAR IJI[5695222]=L"0";
|
064
|
//GetWindowText(hWnd,IJI,5695222);
|
065
|
//ClearCommandUI(L"PreEditControl",IJI);
|
086
|
//rect.left=pt.x;rect.right=pt.y;
|
087
|
HMENU EditMenu=LoadMenu(GetModuleHandle(nullptr),MAKEINTRESOURCE(IDR_MENU_POPU));
|
088
|
HMENU PopuMenu=GetSubMenu(EditMenu,0);
|
089
|
if (SendMessage(hWnd,EM_CANUNDO,0,0))
|
091
|
EnableMenuItem(PopuMenu,IDM_EDIT_UNDO,MF_ENABLED);
|
095
|
EnableMenuItem(PopuMenu,IDM_EDIT_UNDO,MF_GRAYED);
|
098
|
SendMessage(hWnd,EM_GETSEL,( WPARAM )&n,( LPARAM )&m);
|
101
|
EnableMenuItem(PopuMenu,IDM_EDIT_CLEAR,MF_GRAYED);
|
102
|
EnableMenuItem(PopuMenu,IDM_EDIT_COPY,MF_GRAYED);
|
103
|
EnableMenuItem(PopuMenu,IDM_EDIT_CUT,MF_GRAYED);
|
107
|
EnableMenuItem(PopuMenu,IDM_EDIT_CLEAR,MF_ENABLED);
|
108
|
EnableMenuItem(PopuMenu,IDM_EDIT_COPY,MF_ENABLED);
|
109
|
EnableMenuItem(PopuMenu,IDM_EDIT_CUT,MF_ENABLED);
|
111
|
EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_BYCOMMAND|MF_ENABLED);
|
113
|
if (OpenClipboard(hWnd))
|
115
|
if (GetClipboardData(CF_TEXT))
|
117
|
EnableMenuItem(PopuMenu,IDM_EDIT_PASTE,MF_ENABLED);
|
121
|
EnableMenuItem(PopuMenu,IDM_EDIT_PASTE,MF_GRAYED);
|
127
|
EnableMenuItem(PopuMenu,IDM_EDIT_PASTE,MF_GRAYED);
|
130
|
if (GetWindowTextLength(hWnd)==0)
|
132
|
EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_GRAYED);
|
136
|
if (GetWindowTextLength(hWnd)==(m-n)||m-n==-1)
|
137
|
EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_GRAYED);
|
139
|
EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_ENABLED);
|
141
|
//HiliteMenuItem(hWnd,PopuMenu,IDI_RESTART,MF_BYCOMMAND|MF_HILITE);
|
142
|
//WCHAR st[10]={'0'};
|
143
|
//wsprintf(st,L"ST=: %d",x);
|
144
|
//MessageBox(NULL,st,L"Text Long",MB_OK);
|
145
|
//if(SendMessage(hWnd,WM_,CF_TEXT,0)
|
146
|
//InsertMenu(PopuMenu,IDR_SETTING,MF_ENABLED,IDM_ECUT,L"PASTE");
|
147
|
TrackPopupMenuEx(PopuMenu,TPM_RIGHTBUTTON,pt.x,pt.y,hWnd,NULL);
|
151
|
//MessageBox(NULL,L"Font",L"Setting Font",MB_OK);
|
159
|
if (GetKeyState(VK_MENU)<0)
|
160
|
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_SETBOX), hWnd, OpenOpDlg);
|
163
|
if (GetKeyState(VK_MENU)<0)
|
165
|
//MessageBox(NULL,L"Alt+F2 is Update",L"Alt+F2",MB_OK);
|
166
|
SendMessage(hWnd,WM_COMMAND,IDR_UPDATA,0);
|
170
|
if (GetKeyState(VK_MENU)<0)
|
181
|
if (GetKeyState(VK_CONTROL)<0)
|
183
|
//MessageBox(NULL,L"Select All",L"Ctrl+A",MB_OK);
|
185
|
SendMessage(hWnd,EM_GETSEL,( WPARAM )&start,( LPARAM )&end);
|
186
|
if (GetWindowTextLength(hWnd)==(end-start)||end-start==-1)
|
189
|
SendMessage(hWnd,EM_SETSEL,0,-1);
|
193
|
MessageBeep(MB_OK); //Test
|
204
|
/*http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx wParam Virtual Key Value! */
|
215
|
return CallWindowProc(OldEditWndProc,hWnd, uMsg, wParam, lParam);
|
一定不要忘记最后调用旧的窗口处理函数,特定消息必须截断不然会调用默认消息,你的努力就白费了。
好吧说到这里有点偏了,这个超类化的经历与WiFiAssistant很重要,首先,用户面对的是一个界面,
以这个界面为例,我给用户提供了以下几个功能:
1.一键开启虚拟WiFi,这个会随机产生随机字符串作为用户名和密码,
2.关闭WiFi
3.开启WiFi
4.显示密码
5.取消定时关机
6.定时关机
7.获取管理员权限
如果要随机产生字符串,一般的方法是先设置一个常字符串数组,里面的字符一般是从a开始的ANSI字符,我的模板是:
1
|
const WCHAR * cstr= L "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#$%^&*()-=_+,./;\"'<>?~|" ;
|
再初始化随即种子srand((unsigned int) GetTickCount());
这里是选取的系统启动的毫秒数,最后使用随机rand()产生随机数,除以常字符串的大小取余,再获取常字符串cstr[i],这里i就是余数,因为C++ string更加好用,所以整个函数最终用string实现,如下:
01
|
bool GetRandStringUserOrPwd( PWSTR wstr, UINT Size)
|
03
|
const std::wstring templetstr= L "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#$%^&*()-=_+,./;\"'<>?~|" ;
|
07
|
lstr = ( UINT )templetstr.size();
|
08
|
srand ((unsigned int ) GetTickCount());
|
09
|
for (i = 1; i < Size; i++)
|
12
|
produce += templetstr.substr(k,1);
|
15
|
wcscpy_s(wstr, Size, produce.c_str());
|
16
|
//MessageBox(NULL, produce.c_str(), L"Test", MB_OK);
|
我习惯用MessageBox测试程序,当我运行GetRandStringUserOrPwd,开启MessageBox,用户名和密码随机产生获得不一样的结果,但是注释掉MessageBox后,二者的随机数值确是一样,虽然我们选取的是计算机的启动时间,以毫秒计,但是计算机的运行速度是非常快的,所以在产生用户名随机数后,我添加了一段代码:
没错就是让它休息一下,500毫秒虽然能够感觉出来,但是对于随机生成的用户名和密码造成差异还是可取的。