接上篇: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 |
} |