WiFiAssistant 无线承载网络设置助手的开发历程(二)

接上篇: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 }
处理了WM_CHAR禁止输入特定字符 和WM_PASTE 中限制字符大小, 
关于显示密码,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 }
说到定时关机,up/down 控件老费功夫了。最后用CreateUpDownControl解决问题绑定伙伴。 
定时关机一定得注意先提权,再调用,最后得把权限恢复,注意,不要把重启和关机搞混了,一个一个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
只要双击upm就可以升级版本,并且upm自己也被修改了。利用宏定义可以非常方便的自动更新版本 
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 }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章