今年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控件,因爲默認的記事本的菜單不太習慣,所以就自己超了下,子類化因爲沒掌握好就沒有使用。
WNDCLASSEX PreEditEx;
ZeroMemory(&PreEditEx,sizeof(PreEditEx));
PreEditEx.cbSize=sizeof(WNDCLASSEX);
GetClassInfoEx(0,L"EDIT",&PreEditEx);
OldEditWndProc=PreEditEx.lpfnWndProc;
PreEditEx.lpfnWndProc=PreEditExWndProc;
//PreEditEx.lpszMenuName=
PreEditEx.lpszClassName=L"PreEditControl";
RegisterClassEx(&PreEditEx);
OldEditWndProc是函數指針,用來保留老的窗口處理函數
LRESULT (CALLBACK* OldEditWndProc)(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
最後就是自己寫窗口函數
LRESULT CALLBACK PreEditExWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
//PAINTSTRUCT ps;
//HDC hdc;
//RECT rt;
//HGDIOBJ oldPen;
int mId,mEvent;
switch (uMsg)
{
case WM_CREATE:
{
//HMENU PopuMenu=GetMenu(hWnd);
//if(PopuMenu==NULL)
// MessageBox(NULL,L"Menu is error HM",L"Error",MB_OK);
//if(InsertMenu(PopuMenu,2, MF_BYPOSITION, IDM_EXIT,L"Exit")==TRUE)
//{
// MessageBox(NULL,L"Menu is OK",L"OK",MB_OK);
//}
//else
//{
// MessageBox(NULL,L"Menu is error",L"Error",MB_OK);
//}
//SetMenu(hWnd,PopuMenu);
}
break;
case WM_COMMAND:
mId = LOWORD(wParam);
mEvent = HIWORD(wParam);
switch(mId)
{
case IDM_EDIT_UNDO:
SendMessage(hWnd,EM_UNDO,0,0L);
break;
case IDM_EDIT_COPY:
SendMessage(hWnd,WM_COPY,0,0L);
break;
case IDM_EDIT_PASTE:
SendMessage(hWnd,WM_PASTE,0,0L);
break;
case IDM_EDIT_CUT:
SendMessage(hWnd,WM_CUT,0,0L);
break;
case IDM_EDIT_SELECTALL:
SendMessage(hWnd, EM_SETSEL, 0, -1);
SendMessage(hWnd,EM_SCROLLCARET,0,0L);
//SendMessage(hWnd,
break;
case IDM_EDIT_CLEAR:
SendMessage(hWnd,WM_CLEAR,0,0L);
break;
case IDR_SETTING:
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_SETBOX), hWnd, OpenOpDlg);
break;
case IDR_UPDATA:
{
MessageBox(NULL,L"Alt+F2 is Update",L"Alt+F2",MB_OK);
//std::
}
break;
case IDM_CLEAR_UI:
{
SetWindowText(hWnd,L"");
//WCHAR IJI[5695222]=L"0";
//GetWindowText(hWnd,IJI,5695222);
//ClearCommandUI(L"PreEditControl",IJI);
}
break;
case IDI_RESTART:
RestartShell();
break;
case IDR_EXIT:
PostQuitMessage(0);
break;
default:
break;
}
break;
case WM_PAINT:
break;
case WM_RBUTTONUP:
{
//GetFocus
//RECT rect;
POINT pt;
GetCursorPos(&pt);
//rect.left=pt.x;rect.right=pt.y;
HMENU EditMenu=LoadMenu(GetModuleHandle(nullptr),MAKEINTRESOURCE(IDR_MENU_POPU));
HMENU PopuMenu=GetSubMenu(EditMenu,0);
if(SendMessage(hWnd,EM_CANUNDO,0,0))
{
EnableMenuItem(PopuMenu,IDM_EDIT_UNDO,MF_ENABLED);
}
else
{
EnableMenuItem(PopuMenu,IDM_EDIT_UNDO,MF_GRAYED);
}
long long n=0,m=0;
SendMessage(hWnd,EM_GETSEL,(WPARAM)&n,(LPARAM)&m);
if(n==m)
{
EnableMenuItem(PopuMenu,IDM_EDIT_CLEAR,MF_GRAYED);
EnableMenuItem(PopuMenu,IDM_EDIT_COPY,MF_GRAYED);
EnableMenuItem(PopuMenu,IDM_EDIT_CUT,MF_GRAYED);
}
else
{
EnableMenuItem(PopuMenu,IDM_EDIT_CLEAR,MF_ENABLED);
EnableMenuItem(PopuMenu,IDM_EDIT_COPY,MF_ENABLED);
EnableMenuItem(PopuMenu,IDM_EDIT_CUT,MF_ENABLED);
}
EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_BYCOMMAND|MF_ENABLED);
//wstring ClipText;
if(OpenClipboard(hWnd))
{
if(GetClipboardData(CF_TEXT))
{
EnableMenuItem(PopuMenu,IDM_EDIT_PASTE,MF_ENABLED);
}
else
{
EnableMenuItem(PopuMenu,IDM_EDIT_PASTE,MF_GRAYED);
}
CloseClipboard();
}
else
{
EnableMenuItem(PopuMenu,IDM_EDIT_PASTE,MF_GRAYED);
CloseClipboard();
}
if(GetWindowTextLength(hWnd)==0)
{
EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_GRAYED);
}
else
{
if(GetWindowTextLength(hWnd)==(m-n)||m-n==-1)
EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_GRAYED);
else
EnableMenuItem(PopuMenu,IDM_EDIT_SELECTALL,MF_ENABLED);
}
//HiliteMenuItem(hWnd,PopuMenu,IDI_RESTART,MF_BYCOMMAND|MF_HILITE);
//WCHAR st[10]={'0'};
//wsprintf(st,L"ST=: %d",x);
//MessageBox(NULL,st,L"Text Long",MB_OK);
//if(SendMessage(hWnd,WM_,CF_TEXT,0)
//InsertMenu(PopuMenu,IDR_SETTING,MF_ENABLED,IDM_ECUT,L"PASTE");
TrackPopupMenuEx(PopuMenu,TPM_RIGHTBUTTON,pt.x,pt.y,hWnd,NULL);
}
return 0;
case WM_SETFONT:
//MessageBox(NULL,L"Font",L"Setting Font",MB_OK);
UpdateWindow(hWnd);
break;
//case WM_CREATE:
case WM_SYSKEYDOWN:
switch(wParam)
{
case VK_F1:
if(GetKeyState(VK_MENU)<0)
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_SETBOX), hWnd, OpenOpDlg);
break;
case VK_F2:
if(GetKeyState(VK_MENU)<0)
{
//MessageBox(NULL,L"Alt+F2 is Update",L"Alt+F2",MB_OK);
SendMessage(hWnd,WM_COMMAND,IDR_UPDATA,0);
}
break;
case VK_F3:
if(GetKeyState(VK_MENU)<0)
RestartShell();
break;
default:
break;
}
case WM_KEYDOWN:
{
switch(wParam)
{
case 'A':
if(GetKeyState(VK_CONTROL)<0)
{
//MessageBox(NULL,L"Select All",L"Ctrl+A",MB_OK);
int start=0,end=0;
SendMessage(hWnd,EM_GETSEL,(WPARAM)&start,(LPARAM)&end);
if(GetWindowTextLength(hWnd)==(end-start)||end-start==-1)
;
else
SendMessage(hWnd,EM_SETSEL,0,-1);
}
break;
case VK_BACK:
MessageBeep(MB_OK);//Test
break;
default:
break;
}
}
break;
case WM_KEYUP:
{
switch(wParam)
{
/*http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx wParam Virtual Key Value! */
case VK_RETURN:
MessageBeep(MB_OK);
break;
default:
break;
}
}
break;
// break;
}
return CallWindowProc(OldEditWndProc,hWnd, uMsg, wParam, lParam);
}
一定不要忘記最後調用舊的窗口處理函數,特定消息必須截斷不然會調用默認消息,你的努力就白費了。
好吧說到這裏有點偏了,這個超類化的經歷與WiFiAssistant很重要,首先,用戶面對的是一個界面,
以這個界面爲例,我給用戶提供了以下幾個功能:
1.一鍵開啓虛擬WiFi,這個會隨機產生隨機字符串作爲用戶名和密碼,
2.關閉WiFi
3.開啓WiFi
4.顯示密碼
5.取消定時關機
6.定時關機
7.獲取管理員權限
如果要隨機產生字符串,一般的方法是先設置一個常字符串數組,裏面的字符一般是從a開始的ANSI字符,我的模板是:
const WCHAR* cstr= L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#$%^&*()-=_+,./;\"'<>?~|";
再初始化隨即種子srand((unsigned int) GetTickCount());
這裏是選取的系統啓動的毫秒數,最後使用隨機rand()產生隨機數,除以常字符串的大小取餘,再獲取常字符串cstr[i],這裏i就是餘數,因爲C++ string更加好用,所以整個函數最終用string實現,如下:
bool GetRandStringUserOrPwd(PWSTR wstr, UINT Size)
{
const std::wstring templetstr= L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#$%^&*()-=_+,./;\"'<>?~|";
UINT i, lstr;
UINT k;
std::wstring produce;
lstr = (UINT)templetstr.size();
srand((unsigned int) GetTickCount());
for (i = 1; i < Size; i++)
{
k = rand() % lstr;
produce += templetstr.substr(k,1);
}
wcscpy_s(wstr, Size, produce.c_str());
//MessageBox(NULL, produce.c_str(), L"Test", MB_OK);
return true;
}
我習慣用MessageBox測試程序,當我運行GetRandStringUserOrPwd,開啓MessageBox,用戶名和密碼隨機產生獲得不一樣的結果,但是註釋掉MessageBox後,二者的隨機數值確是一樣,雖然我們選取的是計算機的啓動時間,以毫秒計,但是計算機的運行速度是非常快的,所以在產生用戶名隨機數後,我添加了一段代碼:
Sleep(500);
沒錯就是讓它休息一下,500毫秒雖然能夠感覺出來,但是對於隨機生成的用戶名和密碼造成差異還是可取的。
WiFi SSID,KEY是否支持中文? 支持,但是,WiFi的SSID Key實質上是32字節的二進制碼,在WirelessHostedNetwork API 內部是用ANSI表示,這就意味着,如果用中文標識,充其量也就是MBCS,UTF8或者是其他代碼頁中讀取只會以其編碼讀取二進制,並不能夠轉換編碼,這就很容易出現“非法的ANSI字符”這個錯誤,那麼如何限制輸入中文呢?我們將Edit改造一番,還是上面的超類化,實現過程如下:
LRESULT CALLBACK LimitEditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CHAR:
{
//if return;
TCHAR ch = (TCHAR) wParam;
if (!(ch >= _T('!') && ch <= _T('~')||ch == VK_BACK))
return 0;
}
break;
case WM_PASTE:
{
OpenClipboard(hWnd);
HGLOBAL hMem = GetClipboardData(CF_UNICODETEXT);
if (hMem)
{
LPWSTR lpstr=(LPWSTR)GlobalLock(hMem) ;
GlobalUnlock(hMem);
if (lpstr != nullptr)
{
std::wstring wstr=lpstr;
GlobalUnlock(hMem);
//MessageBox(hWnd, wstr.c_str(), L"Paste", MB_OK);
if (wstr.length() >= 32)
{
return 0;
}
//check wstr;
}
}
CloseClipboard();
//GetClipboardData
}break;
case WM_MOUSEMOVE:
break;
case WM_LBUTTONUP:
break;
default:
break;
}
return CallWindowProc(OldEditWndProc, hWnd, message, wParam, lParam);
}
處理了WM_CHAR禁止輸入特定字符 和WM_PASTE 中限制字符大小,
關於顯示密碼,ES_PASSWORD這個消息無法通過GetWindowLongPtr和SetWindowLongPtr進行操作修改,於是我想了一個笨辦法,CheckBox 本質是Button,那麼就有點擊事件,但點擊時,就去查看CheckBox是否被選取,如果被選取,就獲取密碼框的文本,銷燬密碼框,重新Create一個沒有ES_PASSWORD屬性的密碼框,並將獲取的文本SetWindowText發過去,具體代碼如下:
HWND hEdKey = GetDlgItem(hWnd, IDC_LIMIT_EDIT);
if (Button_GetCheck(GetDlgItem(hWnd, IDC_CHECKBT_PAW)) == BST_CHECKED)
{
WCHAR text[32] = { 0 };
GetWindowText(hEdKey, text, 32);
SendMessage(GetDlgItem(hWnd, IDC_LIMIT_EDIT), WM_CLOSE, wParam, lParam);
HWND hLimit = CreateWindowEx(WndStyle::dwEditEx, LimitEdit, L"", WndStyle::dwEdit, 110, 120, 200, 25, hWnd, HMENU(IDC_LIMIT_EDIT), hInst, nullptr);
SetWindowText(hLimit, text);
SendMessage(hLimit, EM_SETLIMITTEXT, (WPARAM) 32, lParam);
SendMessage(hLimit, WM_SETFONT, (WPARAM) hFont, lParam);
SendMessage(hEdKey, WVR_REDRAW, wParam, lParam);
}
else
{
WCHAR text[32] = { 0 };
GetWindowText(hEdKey, text, 32);
SendMessage(GetDlgItem(hWnd, IDC_LIMIT_EDIT), WM_CLOSE, wParam, lParam);
HWND hLimit = CreateWindowEx(WndStyle::dwEditEx, LimitEdit, L"", WndStyle::dwEdit | ES_PASSWORD, 110, 120, 200, 25, hWnd, HMENU(IDC_LIMIT_EDIT), hInst, nullptr);
SetWindowText(hLimit, text);
SendMessage(hLimit, EM_SETLIMITTEXT, (WPARAM) 32, lParam);
}
一般來說就算頻繁的點擊也不會造成程序的問題。
開啓WiFi和關閉WiFi這兩個功能實現了很久,cnblogs有一篇 翻譯就詳細講了如何開啓無線承載網絡,首先一定得注意檢查服務是否開啓,包括SharedAccess(ICS)WlanSvc,當然還需要檢查網絡是否暢通,一切準備好了以後,就需要初始化打開無線句柄WlanOpenHandle,WlanHostedNetworkInitSettings,配置WlanHostedNetworkSetProperty,設置第二Key,WlanHostedNetworkSetSecondaryKey,這裏提出來,第一key是系統生成的,所謂輸入的都是設置的第二key,最後WlanHostedNetworkForceStart。切記句柄得關閉。
關閉也就是先打開句柄,再調用WlanHostedNetworkForceStop,我是用的是強制版本,強制掉線的。
說到這裏,開啓WiFi過程中有很多錯誤,如何輸出錯誤代碼?我的機制就是定義錯誤代碼常量,通過GetErrorMessageString獲得錯誤代碼字符串,在調用結束後,檢查錯誤代碼:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// WirelessErrorType.h
//
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef WIRELESSERRORTYPE_H
#define WIRELESSERRORTYPE_H
#ifndef MAX_ERROR_STRING
#define MAX_ERROR_STRING 512
#endif
#define ERRORTYPE_SUCCESS (LRESULT)0L
//no Internet Online
#define NO_INTENET_ONLINE (LRESULT)21L
//No wireless device was found
#define NO_WIRELESS_DEVICE (LRESULT)22L
//Operating systems are not supported
#define SYSTEM_NOT_SUPPORT (LRESULT)23L
//No wireless network adapter was found
#define NO_WIRELESS_ADAPTER (LRESULT)24L
//Wlan API version is low not support
#define WLAN_API_VERLOW_NOT_SUPPORT (LRESULT)25L
#define WLAN_HOSTED_CANNOT_INIT (LRESULT)26L
#define INETSHARD_CONNECTION_ERROR (LRESULT)27L
#define CLOSE_WIFIHOSTED_ERROR (LRESULT)28L
#define SET_SECONDKEY_ERROR (LRESULT)29L
#define WLANHOSTED_FORCE_START_ERROR (LRESULT)30L
#define HOSTEDNETWORK_DISABLE_BY_GROUPPOLICY (LRESULT)31L
#define WLANHANDLEOPEN_ALLOCATE_MEMORY (LRESULT)32L
#define WLANHANDLEOPEN_ERROR_INVALID_PARAMETER (LRESULT)33L
#define WHO_ERROR_REMOTE_SESSION_LIMIT_EXCEEDED (LRESULT)34L
#define SERVICE_NOT_START (LRESULT)35L
#define COM_COMPONENT_FAILED_TO_INITIALIZE (LRESULT)36L
#define SC_HANDLE_OPEN_ERROR (LRESULT)37L
#define WLANSVC_START_ERROR (LRESULT)38L
#define WLANSVC_STOP_ERROR (LRESULT)39L
//Get Error Message String .
void WINAPI GetErrorMessageString(LRESULT hr, PWSTR pstr);
#endif
/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// WirelessErrorType.cpp
//
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define ERROR_INTERNAL
#include "stdafx.h"
#include"WirelessErrorType.h"
void WINAPI GetErrorMessageString(LRESULT hr,PWSTR pstr)
{
switch (hr)
{
case ERRORTYPE_SUCCESS:
wcscpy_s(pstr, MAX_ERROR_STRING, L"No Error!");
break;
case NO_INTENET_ONLINE:
wcscpy_s(pstr, MAX_ERROR_STRING, L"No network connection!");
break;
case NO_WIRELESS_DEVICE:
wcscpy_s(pstr, MAX_ERROR_STRING, L"No wireless network device driver!");
break;
case SYSTEM_NOT_SUPPORT:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Operating systems are not supported!");
break;
case WLAN_API_VERLOW_NOT_SUPPORT:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Wlan API version is low not support!");
break;
case WLAN_HOSTED_CANNOT_INIT:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Wlan Hosted Network can not Initialize!");
break;
case INETSHARD_CONNECTION_ERROR:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Network sharing can not be achieved!");
break;
case CLOSE_WIFIHOSTED_ERROR:
wcscpy_s(pstr, MAX_ERROR_STRING, L"WirelessHostedNetwork can not close!");
break;
case SET_SECONDKEY_ERROR:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Failed to set user key!");
break;
case WLANHOSTED_FORCE_START_ERROR:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Wlan can not be forced open!");
break;
case HOSTEDNETWORK_DISABLE_BY_GROUPPOLICY:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Hosted Network is disabled by group policy on a domain");
break;
case WLANHANDLEOPEN_ALLOCATE_MEMORY:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Failed to allocate memory to create the client context!");
break;
case WLANHANDLEOPEN_ERROR_INVALID_PARAMETER:
wcscpy_s(pstr, MAX_ERROR_STRING, L"pdwNegotiatedVersion is NULL, phClientHandle is NULL, or pReserved is not NULL!");
break;
case WHO_ERROR_REMOTE_SESSION_LIMIT_EXCEEDED:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Too many handles have been issued by the server");
break;
case SERVICE_NOT_START:
wcscpy_s(pstr, MAX_ERROR_STRING, L"The service did not start.");
break;
case COM_COMPONENT_FAILED_TO_INITIALIZE:
wcscpy_s(pstr, MAX_ERROR_STRING, L"COM component failed to initialize.");
break;
case SC_HANDLE_OPEN_ERROR:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Service Manager fails to open.");
break;
case WLANSVC_START_ERROR:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Wireless Auto Configuration service failed to start.");
break;
case WLANSVC_STOP_ERROR:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Stop Service Error!");
break;
default:
wcscpy_s(pstr, MAX_ERROR_STRING, L"Unknown Error!");
break;
}
}
說到定時關機,up/down 控件老費功夫了。最後用CreateUpDownControl解決問題綁定夥伴。
定時關機一定得注意先提權,再調用,最後得把權限恢復,注意,不要把重啓和關機搞混了,一個一個TRUE,一個FALSE。具體代碼在下面有項目的git地址,所以就不貼代碼了。
還有那個以管理員啓動按鈕,爲什麼不直接修改清單文件?事實上關閉WiFi,設置定時關機並不需要管理員,所以就沒有修改清單文件,有寫功能需要管理員運行的,再未取得管理員權限時會通過EnableWindow()禁用,在程序啓動後開始用IsUserAnAdmin()檢測是否以管理員權限運行,並把值保存在namespace Global{bool IsAdmin}全局變量,(用名稱空間限定獲得更好的隔離)。那個按鈕使用了Button_SetElevationRequiredState宏,這個宏能夠是按鈕顯示UAC圖標。
判斷系統版本,我直接使用了IsWindows7OrGreater() 結果發現VS2012 WDE不支持,8.0API中沒有; 2013(8.1SDK)新增的,於是就用了#if defined(_MSC_VER)&&_MSC_VER>=1800 分別實現2012 2013的;2012使用了OSVERSIONINFO;GetVersionEx,微軟MSDN說GetVersionEx以後可能不使用了。XP快要退出舞臺了,所以在程序中果斷禁止了支持XP。
在設置字體的時候發現,微軟雅黑字體在Windows7上耗資太大不美觀,於是又分別設置了字體名,Windows8/8.1都是Microsoft Yaihe UI,windows7 是MS Shell Dlg(這個是是個映射,系統查找註冊表找到這個字體)
配置文件選了XML,不料XmlLite 這廝並不好玩,一下就是全讀取,搞半天沒懂,果斷用std::wstring 耍了一下小聰明。最後寫的時候還是規矩用XmlLite的Write了。
自修改版本寫了兩個有意思的批處理,互相調用,
:::::::::::::::::::::::::::::::::::::::::::::
:::static.bat
@echo off
::Globa SET
if /i "%1"=="" (
set BDT=1
) else (
SET BDT=%1
)
SET MAX=1
SET MIN=0
SET PATCH=0
::Write upm.bat
echo ^@echo off >upm.bat
echo SET mvr=%MAX% >>upm.bat
echo SET mir=%MIN% >>upm.bat
echo SET par=%PATCH% >>upm.bat
echo SET bdt=%BDT% >>upm.bat
echo echo ^^/^^*Defined PreEdit Version^^*^/ ^>upver.h >>upm.bat
echo echo ^/^/ Please #include ^"upver.h^" ^>^>upver.h >>upm.bat
echo echo #define BUILD_TIME %%bdt%% ^>^>upver.h >>upm.bat
echo echo #define PATCH_TIME %%par%% ^>^>upver.h >>upm.bat
echo echo #define MINJOR_VERSION %%mir%% ^>^>upver.h >>upm.bat
echo echo #define MAJOR_VERSION %%mvr%% ^>^>upver.h >>upm.bat
echo SET /a bdt+=1 >>upm.bat
echo call %%~dp0static.bat %%bdt%% >>upm.bat
echo goto :EOF >>upm.bat
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::upm.bat
@echo off
SET mvr=1
SET mir=0
SET par=0
SET bdt=20
echo ^/^*Defined PreEdit Version^*/ >upver.h
echo // Please #include "upver.h" >>upver.h
echo #define BUILD_TIME %bdt% >>upver.h
echo #define PATCH_TIME %par% >>upver.h
echo #define MINJOR_VERSION %mir% >>upver.h
echo #define MAJOR_VERSION %mvr% >>upver.h
SET /a bdt+=1
call %~dp0static.bat %bdt%
goto :EOF
只要雙擊upm就可以升級版本,並且upm自己也被修改了。利用宏定義可以非常方便的自動更新版本 ,如果要修改大版本則需要修改static.bat
upver.h
/*Defined PreEdit Version*/
// Please #include "upver.h"
#define BUILD_TIME 19
#define PATCH_TIME 0
#define MINJOR_VERSION 0
#define MAJOR_VERSION 1
#ifndef VERSION_CONFIG_H
#define VERSION_CONFIG_H
#include "upver.h"
#define TOSTR_(a) L#a
#define TOSTR(a) TOSTR_(a)
#define TOSTRING(str) TOSTR(str)
//Alt+153 ™
#define CAMP L"Huxizero™ Studio. All Rights Reserved.\0"
#ifdef _WIN64
#define APPDEC L"WiFiAssistant™ 64BIT\0"
#else
#define APPDEC L"WiFiAssistant™ 32BIT\0"
#endif
#define PROJECTNAME L"WiFiAssistant.exe\0"
#define PRODUCTNAME "WiFiAssistant™ VirtualWiFi Auto Setting Assistant\0"
#define LEGALTRADMARKS L"Huxizero™\0"
#define YEAR L"2013"
#ifdef MAJOR_VERSION
#define MAJOR MAJOR_VERSION
#else
#define MAJOR 1
#endif
#ifdef MINJOR_VERSION
#define MINOR MINJOR_VERSION
#else
#define MINOR 0
#endif
#ifdef PATCH_TIME
#define PATCHOR PATCH_TIME
#else
#define PATCHOR 1
#endif
#ifdef BUILD_TIME
#define BUILDTIMER BUILD_TIME
#else
#define BUILDTIMER 1
#endif
#define VERSION_STRING TOSTRING(MAJOR.MINOR.PATCHOR.BUILDTIMER)
#define VERSION_WORDS MAJOR,MINOR,PATCHOR,BUILDTIMER
#endif
WiFiAssistant總計2868-2342行,大半個月,還有很多功能,例如,設備接入管理,性能評估模塊都沒有去實現,臨近畢業,也得自己找出路了。軟件在百度帖吧分享還是出了些問題,一個是假死,有部分無線網卡確實無法正確開啓虛擬Wifi,所以程序假死,設置共享的模塊暫時容易出現錯誤,因爲,它找的是連接的網絡適配器,所以,有多個連通適配器的,有可能出現錯誤。
好了,不多說,發代碼地址:http://git.oschina.net/ipvb/WiFiAssistant 支持OSChina
順便貼下最近的錯誤處理機制:
/****************************************************************************************************************************
* ErrorMessageInvoke.h
*
*
******************************************************************************************************************************/
#ifndef ERRORMESSAGEINVOKE_H
#define ERRORMESSAGEINVOKE_H
#include "InternalOpt.h"
#define EMINVOKE_MAX_STRING 256
/****Error Defined Start****/
#define EMI_NO_ERROR 0
#define EMI_INIT_ERROR 1
/*********End defined*******/
typedef struct _ErrorInfo{
int LastErrorId;
uint32_t NumberOfTimes;
}ErrorInfo,*PErrorInfo;
void WINAPI SetErrorCode(const int eId);
void WINAPI ReSetErrorCode();
int WINAPI GetErrorCodeInformation(PErrorInfo prInfo);
int WINAPI GetErrorCodeLastId();
bool WINAPI FormatErrorMessageInvoke(int eId,wchar_t *str,int StrSize);
#endif
///////////////////////////////////////////////////////////////////
/****************************************************************************************************************************
* ErrorMessageInvoke
*
*
******************************************************************************************************************************/
#include "stdhd.h"
#include "ErrorMessageInvoke.h"
static ErrorInfo einfo = { 0, 0 };
void WINAPI SetErrorCode(const int eId)
{
einfo.LastErrorId = eId;
einfo.NumberOfTimes += 1;
}
void WINAPI ReSetErrorCode()
{
einfo.LastErrorId = 0;
einfo.NumberOfTimes = 0;
}
int WINAPI GetErrorCodeInformation(PErrorInfo prInfo)
{
prInfo->LastErrorId = einfo.LastErrorId;
prInfo->NumberOfTimes = einfo.NumberOfTimes;
return prInfo->LastErrorId;
}
int WINAPI GetErrorCodeLastId()
{
return einfo.LastErrorId;
}
bool WINAPI FormatErrorMessageInvoke(int eId, wchar_t *str, int StrSize)
{
switch (eId)
{
case 0:
break;
default:
break;
}
return true;
}
@