接上篇:WiFiAssistant 無線承載網絡設置助手的開發歷程(一)
http://blog.csdn.net/huxizero10/article/details/17521327
WiFi SSID,KEY是否支持中文? 支持,但是,WiFi的SSID Key實質上是32字節的二進制碼,在WirelessHostedNetwork API 內部是用ANSI表示,這就意味着,如果用中文標識,充其量也就是MBCS,UTF8或者是其他代碼頁中讀取只會以其編碼讀取二進制,並不能夠轉換編碼,這就很容易出現“非法的ANSI字符”這個錯誤,那麼如何限制輸入中文呢?我們將Edit改造一番,還是上面的超類化,實現過程如下:
01 |
LRESULT CALLBACK
LimitEditProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) |
02 |
{ |
03 |
switch (message) |
04 |
{ |
05 |
case WM_CHAR: |
06 |
{ |
07 |
//if
return; |
08 |
TCHAR ch
= ( TCHAR )
wParam; |
09 |
if (!(ch
>= _T( '!' )
&& ch <= _T( '~' )||ch
== VK_BACK)) |
10 |
return 0; |
11 |
} |
12 |
break ; |
13 |
case WM_PASTE: |
14 |
{ |
15 |
OpenClipboard(hWnd); |
16 |
HGLOBAL hMem
= GetClipboardData(CF_UNICODETEXT); |
17 |
if (hMem) |
18 |
{ |
19 |
LPWSTR lpstr=( LPWSTR )GlobalLock(hMem)
; |
20 |
GlobalUnlock(hMem); |
21 |
if (lpstr
!= nullptr) |
22 |
{ |
23 |
std::wstring
wstr=lpstr; |
24 |
GlobalUnlock(hMem); |
25 |
//MessageBox(hWnd,
wstr.c_str(), L"Paste", MB_OK); |
26 |
if (wstr.length()
>= 32) |
27 |
{ |
28 |
return 0; |
29 |
} |
30 |
//check
wstr; |
31 |
} |
32 |
} |
33 |
CloseClipboard(); |
34 |
//GetClipboardData |
35 |
} break ; |
36 |
case WM_MOUSEMOVE: |
37 |
break ; |
38 |
case WM_LBUTTONUP: |
39 |
break ; |
40 |
default : |
41 |
break ; |
42 |
} |
43 |
return CallWindowProc(OldEditWndProc,
hWnd, message, wParam, lParam); |
44 |
} |
關於顯示密碼,ES_PASSWORD這個消息無法通過GetWindowLongPtr和SetWindowLongPtr進行操作修改,於是我想了一個笨辦法,CheckBox 本質是Button,那麼就有點擊事件,但點擊時,就去查看CheckBox是否被選取,如果被選取,就獲取密碼框的文本,銷燬密碼框,重新Create一個沒有ES_PASSWORD屬性的密碼框,並將獲取的文本SetWindowText發過去,具體代碼如下:
01 |
HWND hEdKey
= GetDlgItem(hWnd, IDC_LIMIT_EDIT); |
02 |
if (Button_GetCheck(GetDlgItem(hWnd,
IDC_CHECKBT_PAW)) == BST_CHECKED) |
03 |
{ |
04 |
WCHAR text[32]
= { 0 }; |
05 |
GetWindowText(hEdKey,
text, 32); |
06 |
SendMessage(GetDlgItem(hWnd,
IDC_LIMIT_EDIT), WM_CLOSE, wParam, lParam); |
07 |
HWND hLimit
= CreateWindowEx(WndStyle::dwEditEx, LimitEdit, L "" ,
WndStyle::dwEdit, 110, 120, 200, 25, hWnd, HMENU (IDC_LIMIT_EDIT),
hInst, nullptr); |
08 |
SetWindowText(hLimit,
text); |
09 |
SendMessage(hLimit,
EM_SETLIMITTEXT, ( WPARAM )
32, lParam); |
10 |
SendMessage(hLimit,
WM_SETFONT, ( WPARAM )
hFont, lParam); |
11 |
SendMessage(hEdKey,
WVR_REDRAW, wParam, lParam); |
12 |
} |
13 |
else |
14 |
{ |
15 |
WCHAR text[32]
= { 0 }; |
16 |
GetWindowText(hEdKey,
text, 32); |
17 |
SendMessage(GetDlgItem(hWnd,
IDC_LIMIT_EDIT), WM_CLOSE, wParam, lParam); |
18 |
HWND hLimit
= CreateWindowEx(WndStyle::dwEditEx, LimitEdit, L "" ,
WndStyle::dwEdit | ES_PASSWORD, 110, 120, 200, 25, hWnd, HMENU (IDC_LIMIT_EDIT),
hInst, nullptr); |
19 |
SetWindowText(hLimit,
text); |
20 |
SendMessage(hLimit,
EM_SETLIMITTEXT, ( WPARAM )
32, lParam); |
21 |
} |
開啓WiFi和關閉WiFi這兩個功能實現了很久,cnblogs有一篇 翻譯就詳細講了如何開啓無線承載網絡,首先一定得注意檢查服務是否開啓,包括SharedAccess(ICS)WlanSvc,當然還需要檢查網絡是否暢通,一切準備好了以後,就需要初始化打開無線句柄WlanOpenHandle,WlanHostedNetworkInitSettings,配置WlanHostedNetworkSetProperty,設置第二Key,WlanHostedNetworkSetSecondaryKey,這裏提出來,第一key是系統生成的,所謂輸入的都是設置的第二key,最後WlanHostedNetworkForceStart。切記句柄得關閉。
關閉也就是先打開句柄,再調用WlanHostedNetworkForceStop,我是用的是強制版本,強制掉線的。
說到這裏,開啓WiFi過程中有很多錯誤,如何輸出錯誤代碼?我的機制就是定義錯誤代碼常量,通過GetErrorMessageString獲得錯誤代碼字符串,在調用結束後,檢查錯誤代碼:
001 |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
002 |
//
WirelessErrorType.h |
003 |
// |
004 |
// |
005 |
// |
006 |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
007 |
#ifndef
WIRELESSERRORTYPE_H |
008 |
#define
WIRELESSERRORTYPE_H |
009 |
010 |
#ifndef
MAX_ERROR_STRING |
011 |
#define
MAX_ERROR_STRING 512 |
012 |
#endif |
013 |
014 |
#define
ERRORTYPE_SUCCESS (LRESULT)0L |
015 |
//no
Internet Online |
016 |
#define
NO_INTENET_ONLINE (LRESULT)21L |
017 |
//No
wireless device was found |
018 |
#define
NO_WIRELESS_DEVICE (LRESULT)22L |
019 |
//Operating
systems are not supported |
020 |
#define
SYSTEM_NOT_SUPPORT (LRESULT)23L |
021 |
//No
wireless network adapter was found |
022 |
#define
NO_WIRELESS_ADAPTER (LRESULT)24L |
023 |
//Wlan
API version is low not support |
024 |
#define
WLAN_API_VERLOW_NOT_SUPPORT (LRESULT)25L |
025 |
#define
WLAN_HOSTED_CANNOT_INIT (LRESULT)26L |
026 |
#define
INETSHARD_CONNECTION_ERROR (LRESULT)27L |
027 |
#define
CLOSE_WIFIHOSTED_ERROR (LRESULT)28L |
028 |
#define
SET_SECONDKEY_ERROR (LRESULT)29L |
029 |
#define
WLANHOSTED_FORCE_START_ERROR (LRESULT)30L |
030 |
#define
HOSTEDNETWORK_DISABLE_BY_GROUPPOLICY (LRESULT)31L |
031 |
#define
WLANHANDLEOPEN_ALLOCATE_MEMORY (LRESULT)32L |
032 |
#define
WLANHANDLEOPEN_ERROR_INVALID_PARAMETER (LRESULT)33L |
033 |
#define
WHO_ERROR_REMOTE_SESSION_LIMIT_EXCEEDED (LRESULT)34L |
034 |
#define
SERVICE_NOT_START (LRESULT)35L |
035 |
#define
COM_COMPONENT_FAILED_TO_INITIALIZE (LRESULT)36L |
036 |
#define
SC_HANDLE_OPEN_ERROR (LRESULT)37L |
037 |
#define
WLANSVC_START_ERROR (LRESULT)38L |
038 |
#define
WLANSVC_STOP_ERROR (LRESULT)39L |
039 |
//Get
Error Message String . |
040 |
void WINAPI
GetErrorMessageString( LRESULT hr, PWSTR pstr); |
041 |
042 |
#endif |
043 |
044 |
///////////////////////////////////////////////////////////////////// |
045 |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
046 |
//
WirelessErrorType.cpp |
047 |
// |
048 |
// |
049 |
// |
050 |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
051 |
052 |
#define
ERROR_INTERNAL |
053 |
#include
"stdafx.h" |
054 |
#include"WirelessErrorType.h" |
055 |
056 |
057 |
058 |
void WINAPI
GetErrorMessageString( LRESULT hr, PWSTR pstr) |
059 |
{ |
060 |
switch (hr) |
061 |
{ |
062 |
case ERRORTYPE_SUCCESS: |
063 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "No
Error!" ); |
064 |
break ; |
065 |
case NO_INTENET_ONLINE: |
066 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "No
network connection!" ); |
067 |
break ; |
068 |
case NO_WIRELESS_DEVICE: |
069 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "No
wireless network device driver!" ); |
070 |
break ; |
071 |
case SYSTEM_NOT_SUPPORT: |
072 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Operating
systems are not supported!" ); |
073 |
break ; |
074 |
case WLAN_API_VERLOW_NOT_SUPPORT: |
075 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Wlan
API version is low not support!" ); |
076 |
break ; |
077 |
case WLAN_HOSTED_CANNOT_INIT: |
078 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Wlan
Hosted Network can not Initialize!" ); |
079 |
break ; |
080 |
case INETSHARD_CONNECTION_ERROR: |
081 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Network
sharing can not be achieved!" ); |
082 |
break ; |
083 |
case CLOSE_WIFIHOSTED_ERROR: |
084 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "WirelessHostedNetwork
can not close!" ); |
085 |
break ; |
086 |
case SET_SECONDKEY_ERROR: |
087 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Failed
to set user key!" ); |
088 |
break ; |
089 |
case WLANHOSTED_FORCE_START_ERROR: |
090 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Wlan
can not be forced open!" ); |
091 |
break ; |
092 |
case HOSTEDNETWORK_DISABLE_BY_GROUPPOLICY: |
093 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Hosted
Network is disabled by group policy on a domain" ); |
094 |
break ; |
095 |
case WLANHANDLEOPEN_ALLOCATE_MEMORY: |
096 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Failed
to allocate memory to create the client context!" ); |
097 |
break ; |
098 |
case WLANHANDLEOPEN_ERROR_INVALID_PARAMETER: |
099 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "pdwNegotiatedVersion
is NULL, phClientHandle is NULL, or pReserved is not NULL!" ); |
100 |
break ; |
101 |
case WHO_ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: |
102 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Too
many handles have been issued by the server" ); |
103 |
break ; |
104 |
case SERVICE_NOT_START: |
105 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "The
service did not start." ); |
106 |
break ; |
107 |
case COM_COMPONENT_FAILED_TO_INITIALIZE: |
108 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "COM
component failed to initialize." ); |
109 |
break ; |
110 |
case SC_HANDLE_OPEN_ERROR: |
111 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Service
Manager fails to open." ); |
112 |
break ; |
113 |
case WLANSVC_START_ERROR: |
114 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Wireless
Auto Configuration service failed to start." ); |
115 |
break ; |
116 |
case WLANSVC_STOP_ERROR: |
117 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Stop
Service Error!" ); |
118 |
break ; |
119 |
default : |
120 |
wcscpy_s(pstr,
MAX_ERROR_STRING, L "Unknown
Error!" ); |
121 |
break ; |
122 |
} |
123 |
} |
定時關機一定得注意先提權,再調用,最後得把權限恢復,注意,不要把重啓和關機搞混了,一個一個TRUE,一個FALSE。具體代碼在下面有項目的git地址,所以就不貼代碼了。
還有那個以管理員啓動按鈕,爲什麼不直接修改清單文件?事實上關閉WiFi,設置定時關機並不需要管理員,所以就沒有修改清單文件,有寫功能需要管理員運行的,再未取得管理員權限時會通過EnableWindow()禁用,在程序啓動後開始用IsUserAnAdmin()檢測是否以管理員權限運行,並把值保存在namespace Global{bool IsAdmin}全局變量,(用名稱空間限定獲得更好的隔離)。那個按鈕使用了Button_SetElevationRequiredState宏,這個宏能夠是按鈕顯示UAC圖標。
判斷系統版本,我直接使用了IsWindows7OrGreater() 結果發現VS2012 WDE不支持,API中沒有 2013新增的,於是就用了#if defined(_MSC_VER)&&_MSC_VER>=1800 分別實現2012 2013的;2012使用了OSVERSIONINFO;GetVersionEx,微軟MSDN說GetVersionEx以後可能不使用了。在程序中果斷禁止了支持XP。
在設置字體的時候發現,微軟雅黑字體在W7上耗資太大不美觀,於是果斷又分別設置了字體名,W8 8.1都是Microsoft Yaihe UI;
配置文件選了XML,不料XmlLite 這廝並不好玩,一下就是全讀取,搞半天沒懂,果斷用std::wstring 耍了一下小聰明。最後寫的時候還是規矩重寫了。
自修改版本卸了兩個有意思的批處理:
01 |
::::::::::::::::::::::::::::::::::::::::::::: |
02 |
:::static.bat |
03 |
@ echo off |
04 |
::Globa
SET |
05 |
if /i "%1" == "" ( |
06 |
set BDT=1 |
07 |
) else ( |
08 |
SET
BDT=%1 |
09 |
) |
10 |
SET
MAX=1 |
11 |
SET
MIN=0 |
12 |
SET
PATCH=0 |
13 |
14 |
::Write
upm.bat |
15 |
echo ^@ echo off
>upm.bat |
16 |
echo SET
mvr=%MAX% >>upm.bat |
17 |
echo SET
mir=%MIN% >>upm.bat |
18 |
echo SET
par=%PATCH% >>upm.bat |
19 |
echo SET
bdt=%BDT% >>upm.bat |
20 |
echo echo ^^/^^*Defined
PreEdit Version^^*^/ ^>upver.h >>upm.bat |
21 |
echo echo ^/^/
Please #include
^"upver.h^" ^>^>upver.h >>upm.bat |
22 |
echo echo #define
BUILD_TIME %%bdt%% ^>^>upver.h >>upm.bat |
23 |
echo echo #define
PATCH_TIME %%par%% ^>^>upver.h >>upm.bat |
24 |
echo echo #define
MINJOR_VERSION %%mir%% ^>^>upver.h >>upm.bat |
25 |
echo echo #define
MAJOR_VERSION %%mvr%% ^>^>upver.h >>upm.bat |
26 |
echo SET
/a bdt+=1 >>upm.bat |
27 |
echo call
%%~dp0static.bat %%bdt%% >>upm.bat |
28 |
echo goto
:EOF >>upm.bat |
29 |
30 |
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
31 |
::upm.bat |
32 |
@ echo off |
33 |
SET
mvr=1 |
34 |
SET
mir=0 |
35 |
SET
par=0 |
36 |
SET
bdt=20 |
37 |
echo ^/^*Defined
PreEdit Version^*/ >upver.h |
38 |
echo //
Please #include
"upver.h" >>upver.h |
39 |
echo #define
BUILD_TIME %bdt% >>upver.h |
40 |
echo #define
PATCH_TIME %par% >>upver.h |
41 |
echo #define
MINJOR_VERSION %mir% >>upver.h |
42 |
echo #define
MAJOR_VERSION %mvr% >>upver.h |
43 |
SET
/a bdt+=1 |
44 |
call
%~dp0static.bat %bdt% |
45 |
goto
:EOF |
upver.h
1 |
/*Defined
PreEdit Version*/ |
2 |
//
Please #include "upver.h" |
3 |
#define
BUILD_TIME 19 |
4 |
#define
PATCH_TIME 0 |
5 |
#define
MINJOR_VERSION 0 |
6 |
#define
MAJOR_VERSION 1 |
01 |
#ifndef
VERSION_CONFIG_H |
02 |
#define
VERSION_CONFIG_H |
03 |
04 |
#include
"upver.h" |
05 |
06 |
#define
TOSTR_(a) L#a |
07 |
#define
TOSTR(a) TOSTR_(a) |
08 |
#define
TOSTRING(str) TOSTR(str) |
09 |
//Alt+153
™ |
10 |
#define
CAMP L"Huxizero™ Studio. All Rights Reserved.\0" |
11 |
#ifdef
_WIN64 |
12 |
#define
APPDEC L"WiFiAssistant™ 64BIT\0" |
13 |
#else |
14 |
#define
APPDEC L"WiFiAssistant™ 32BIT\0" |
15 |
#endif |
16 |
17 |
#define
PROJECTNAME L"WiFiAssistant.exe\0" |
18 |
#define
PRODUCTNAME "WiFiAssistant™ VirtualWiFi Auto Setting Assistant\0" |
19 |
#define
LEGALTRADMARKS L"Huxizero™\0" |
20 |
21 |
#define
YEAR L"2013" |
22 |
23 |
#ifdef
MAJOR_VERSION |
24 |
#define
MAJOR MAJOR_VERSION |
25 |
#else |
26 |
#define
MAJOR 1 |
27 |
#endif |
28 |
29 |
#ifdef
MINJOR_VERSION |
30 |
#define
MINOR MINJOR_VERSION |
31 |
#else |
32 |
#define
MINOR 0 |
33 |
#endif |
34 |
35 |
#ifdef
PATCH_TIME |
36 |
#define
PATCHOR PATCH_TIME |
37 |
#else |
38 |
#define
PATCHOR 1 |
39 |
#endif |
40 |
41 |
#ifdef
BUILD_TIME |
42 |
#define
BUILDTIMER BUILD_TIME |
43 |
#else |
44 |
#define
BUILDTIMER 1 |
45 |
#endif |
46 |
47 |
#define
VERSION_STRING TOSTRING(MAJOR.MINOR.PATCHOR.BUILDTIMER) |
48 |
#define
VERSION_WORDS MAJOR,MINOR,PATCHOR,BUILDTIMER |
49 |
50 |
#endif |
WiFiAssistant總計2868-2342行,大半個月,還有很多功能,例如,設備接入管理,性能評估模塊都沒有去實現,臨近畢業,也得自己找出路了。軟件在百度帖吧分享還是出了些問題,一個是假死,有部分無線網卡確實無法正確開啓虛擬Wifi,所以程序假死,設置共享的模塊暫時容易出現錯誤,因爲,它找的是連接的網絡適配器,所以,有多個連通適配器的,有可能出現錯誤。
好了,不多說,發代碼地址:http://git.oschina.net/ipvb/WiFiAssistant 支持OSChina
順便貼下最近的錯誤處理機制:
01 |
/**************************************************************************************************************************** |
02 |
*
ErrorMessageInvoke.h |
03 |
* |
04 |
* |
05 |
******************************************************************************************************************************/ |
06 |
#ifndef
ERRORMESSAGEINVOKE_H |
07 |
#define
ERRORMESSAGEINVOKE_H |
08 |
#include
"InternalOpt.h" |
09 |
10 |
#define
EMINVOKE_MAX_STRING 256 |
11 |
12 |
/****Error
Defined Start****/ |
13 |
14 |
#define
EMI_NO_ERROR 0 |
15 |
#define
EMI_INIT_ERROR 1 |
16 |
17 |
18 |
/*********End
defined*******/ |
19 |
20 |
21 |
typedef struct _ErrorInfo{ |
22 |
int LastErrorId; |
23 |
uint32_t
NumberOfTimes; |
24 |
}ErrorInfo,*PErrorInfo; |
25 |
26 |
void WINAPI
SetErrorCode( const int eId); |
27 |
void WINAPI
ReSetErrorCode(); |
28 |
int WINAPI
GetErrorCodeInformation(PErrorInfo prInfo); |
29 |
int WINAPI
GetErrorCodeLastId(); |
30 |
bool WINAPI
FormatErrorMessageInvoke( int eId, wchar_t *str, int StrSize); |
31 |
32 |
33 |
#endif |
34 |
35 |
/////////////////////////////////////////////////////////////////// |
36 |
/**************************************************************************************************************************** |
37 |
*
ErrorMessageInvoke |
38 |
* |
39 |
* |
40 |
******************************************************************************************************************************/ |
41 |
#include
"stdhd.h" |
42 |
#include
"ErrorMessageInvoke.h" |
43 |
44 |
static ErrorInfo
einfo = { 0, 0 }; |
45 |
46 |
void WINAPI
SetErrorCode( const int eId) |
47 |
{ |
48 |
einfo.LastErrorId
= eId; |
49 |
einfo.NumberOfTimes
+= 1; |
50 |
} |
51 |
52 |
void WINAPI
ReSetErrorCode() |
53 |
{ |
54 |
einfo.LastErrorId
= 0; |
55 |
einfo.NumberOfTimes
= 0; |
56 |
} |
57 |
58 |
int WINAPI
GetErrorCodeInformation(PErrorInfo prInfo) |
59 |
{ |
60 |
prInfo->LastErrorId
= einfo.LastErrorId; |
61 |
prInfo->NumberOfTimes
= einfo.NumberOfTimes; |
62 |
return prInfo->LastErrorId; |
63 |
} |
64 |
65 |
66 |
int WINAPI
GetErrorCodeLastId() |
67 |
{ |
68 |
return einfo.LastErrorId; |
69 |
} |
70 |
71 |
bool WINAPI
FormatErrorMessageInvoke( int eId, wchar_t *str, int StrSize) |
72 |
{ |
73 |
switch (eId) |
74 |
{ |
75 |
case 0: |
76 |
break ; |
77 |
default : |
78 |
break ; |
79 |
} |
80 |
return true ; |
81 |
} |