今年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控件,因为默认的记事本的菜单不太习惯,所以就自己超了下,子类化因为没掌握好就没有使用。
1 | WNDCLASSEX PreEditEx; |
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) |
002 | { |
003 | //PAINTSTRUCT ps; |
004 | //HDC hdc; |
005 | //RECT rt; |
006 | //HGDIOBJ oldPen; |
007 | int mId,mEvent; |
008 | switch (uMsg) |
009 | { |
026 | case WM_COMMAND: |
027 | mId = LOWORD(wParam); |
028 | mEvent = HIWORD(wParam); |
029 | switch (mId) |
030 | { |
031 | case IDM_EDIT_UNDO: |
032 | SendMessage(hWnd,EM_UNDO,0,0L); |
033 | break ; |
034 | case IDM_EDIT_COPY: |
035 | SendMessage(hWnd,WM_COPY,0,0L); |
036 | break ; |
037 | case IDM_EDIT_PASTE: |
038 | SendMessage(hWnd,WM_PASTE,0,0L); |
039 | break ; |
040 | case IDM_EDIT_CUT: |
041 | SendMessage(hWnd,WM_CUT,0,0L); |
042 | break ; |
043 | case IDM_EDIT_SELECTALL: |
044 | SendMessage(hWnd, EM_SETSEL, 0, -1); |
045 | SendMessage(hWnd,EM_SCROLLCARET,0,0L); |
046 | //SendMessage(hWnd, |
047 | break ; |
048 | case IDM_EDIT_CLEAR: |
049 | SendMessage(hWnd,WM_CLEAR,0,0L); |
050 | break ; |
051 | case IDR_SETTING: |
052 | DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_SETBOX), hWnd, OpenOpDlg); |
053 | break ; |
054 | case IDR_UPDATA: |
055 | { |
056 | MessageBox(NULL,L "Alt+F2 is Update" ,L "Alt+F2" ,MB_OK); |
057 | //std:: |
058 | } |
059 | break ; |
060 | case IDM_CLEAR_UI: |
061 | { |
062 | SetWindowText(hWnd,L "" ); |
063 | //WCHAR IJI[5695222]=L"0"; |
064 | //GetWindowText(hWnd,IJI,5695222); |
065 | //ClearCommandUI(L"PreEditControl",IJI); |
066 | } |
067 | break ; |
068 | case IDI_RESTART: |
069 | RestartShell(); |
070 | break ; |
071 | case IDR_EXIT: |
072 | PostQuitMessage(0); |
073 | break ; |
074 | default : |
075 | break ; |
076 | } |
077 | break ; |
078 | case WM_PAINT: |
079 | break ; |
080 | case WM_RBUTTONUP: |
081 | { |
082 | //GetFocus |
083 | //RECT rect; |
084 | POINT pt; |
085 | GetCursorPos(&pt); |
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)) |
090 | { |
091 | EnableMenuItem(PopuMenu,IDM_EDIT_UNDO,MF_ENABLED); |
092 | } |
093 | else |
094 | { |
095 | EnableMenuItem(PopuMenu,IDM_EDIT_UNDO,MF_GRAYED); |
096 | } |
097 | long long n=0,m=0; |
098 | SendMessage(hWnd,EM_GETSEL,( WPARAM )&n,( LPARAM )&m); |
099 | if (n==m) |
100 | { |
101 | EnableMenuItem(PopuMenu,IDM_EDIT_CLEAR,MF_GRAYED); |
102 | EnableMenuItem(PopuMenu,IDM_EDIT_COPY,MF_GRAYED); |
103 | EnableMenuItem(PopuMenu,IDM_EDIT_CUT,MF_GRAYED); |
104 | } |
105 | else |
106 | { |
107 | EnableMenuItem(PopuMenu,IDM_EDIT_CLEAR,MF_ENABLED); |
108 | EnableMenuItem(PopuMenu,IDM_EDIT_COPY,MF_ENABLED); |
109 | EnableMenuItem(PopuMenu,IDM_EDIT_CUT,MF_ENABLED); |
110 | } |
111 | EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_BYCOMMAND|MF_ENABLED); |
112 | //wstring ClipText; |
113 | if (OpenClipboard(hWnd)) |
114 | { |
115 | if (GetClipboardData(CF_TEXT)) |
116 | { |
117 | EnableMenuItem(PopuMenu,IDM_EDIT_PASTE,MF_ENABLED); |
118 | } |
119 | else |
120 | { |
121 | EnableMenuItem(PopuMenu,IDM_EDIT_PASTE,MF_GRAYED); |
122 | } |
123 | CloseClipboard(); |
124 | } |
125 | else |
126 | { |
127 | EnableMenuItem(PopuMenu,IDM_EDIT_PASTE,MF_GRAYED); |
128 | CloseClipboard(); |
129 | } |
130 | if (GetWindowTextLength(hWnd)==0) |
131 | { |
132 | EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_GRAYED); |
133 | } |
134 | else |
135 | { |
136 | if (GetWindowTextLength(hWnd)==(m-n)||m-n==-1) |
137 | EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_GRAYED); |
138 | else |
139 | EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_ENABLED); |
140 | } |
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); |
148 | } |
149 | return 0; |
150 | case WM_SETFONT: |
151 | //MessageBox(NULL,L"Font",L"Setting Font",MB_OK); |
152 | UpdateWindow(hWnd); |
153 | break ; |
154 | //case WM_CREATE: |
155 | case WM_SYSKEYDOWN: |
156 | switch (wParam) |
157 | { |
158 | case VK_F1: |
159 | if (GetKeyState(VK_MENU)<0) |
160 | DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_SETBOX), hWnd, OpenOpDlg); |
161 | break ; |
162 | case VK_F2: |
163 | if (GetKeyState(VK_MENU)<0) |
164 | { |
165 | //MessageBox(NULL,L"Alt+F2 is Update",L"Alt+F2",MB_OK); |
166 | SendMessage(hWnd,WM_COMMAND,IDR_UPDATA,0); |
167 | } |
168 | break ; |
169 | case VK_F3: |
170 | if (GetKeyState(VK_MENU)<0) |
171 | RestartShell(); |
172 | break ; |
173 | default : |
174 | break ; |
175 | } |
176 | case WM_KEYDOWN: |
177 | { |
178 | switch (wParam) |
179 | { |
180 | case 'A' : |
181 | if (GetKeyState(VK_CONTROL)<0) |
182 | { |
183 | //MessageBox(NULL,L"Select All",L"Ctrl+A",MB_OK); |
184 | int start=0,end=0; |
185 | SendMessage(hWnd,EM_GETSEL,( WPARAM )&start,( LPARAM )&end); |
186 | if (GetWindowTextLength(hWnd)==(end-start)||end-start==-1) |
187 | ; |
188 | else |
189 | SendMessage(hWnd,EM_SETSEL,0,-1); |
190 | } |
191 | break ; |
192 | case VK_BACK: |
193 | MessageBeep(MB_OK); //Test |
194 | break ; |
195 | default : |
196 | break ; |
197 | } |
198 | } |
199 | break ; |
200 | case WM_KEYUP: |
201 | { |
202 | switch (wParam) |
203 | { |
204 | /*http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx wParam Virtual Key Value! */ |
205 | case VK_RETURN: |
206 | MessageBeep(MB_OK); |
207 | break ; |
208 | default : |
209 | break ; |
210 | } |
211 | } |
212 | break ; |
213 | // break; |
214 | } |
215 | return CallWindowProc(OldEditWndProc,hWnd, uMsg, wParam, lParam); |
216 | } |
好吧说到这里有点偏了,这个超类化的经历与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) |
02 | { |
03 | const std::wstring templetstr= L "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#$%^&*()-=_+,./;\"'<>?~|" ; |
04 | UINT i, lstr; |
05 | UINT k; |
06 | std::wstring produce; |
07 | lstr = ( UINT )templetstr.size(); |
08 | srand ((unsigned int ) GetTickCount()); |
09 | for (i = 1; i < Size; i++) |
10 | { |
11 | k = rand () % lstr; |
12 | produce += templetstr.substr(k,1); |
13 | |
14 | } |
15 | wcscpy_s(wstr, Size, produce.c_str()); |
16 | //MessageBox(NULL, produce.c_str(), L"Test", MB_OK); |
17 | return true ; |
18 | } |
1 | Sleep(500); |