今年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); |