C++程序中使用Windows系統(tǒng)Native Wifi API的基本教程
Windows應(yīng)用想要實(shí)現(xiàn)連接wifi,監(jiān)聽wifi信號(hào),斷開連接等功能,用NativeWifi API是個(gè)不錯(cuò)的選擇。
打開MSDN,搜索NativeWifi Api,找到Native Wifi頁(yè)。在這里。
信息量很大,如果像我著急實(shí)現(xiàn)上述功能,看海量的文檔有些來(lái)不及。如果直接給我例子,在運(yùn)行中調(diào)試,閱讀代碼,效率會(huì)更高。
但是,我并沒(méi)有成功。首先,Sample在SDK中,參見這里。我下載幾次都失敗了,最后放棄這條路。后來(lái)同事給了我一份Sample,我不敢確定是否就是這個(gè),但是代碼寫的也是很晦澀。我的初衷是簡(jiǎn)單的使用這些API的例子。
看來(lái)還是自己動(dòng)手吧??聪嚓P(guān)API,如果不懂,就找有經(jīng)驗(yàn)人的例子。
幾經(jīng)周折,終于實(shí)現(xiàn)我的需求。讓我慢慢道來(lái)。
1.獲得可用AP列表
參見WlanGetAvailableNetworkList的官方文檔,下面有例子。
DWORD WINAPI WlanGetAvailableNetworkList( _In_ HANDLE hClientHandle, _In_ const GUID *pInterfaceGuid, _In_ DWORD dwFlags, _Reserved_ PVOID pReserved, _Out_ PWLAN_AVAILABLE_NETWORK_LIST *ppAvailableNetworkList );
由可用列表便可以找到當(dāng)前哪個(gè)AP正在連接,并顯示信號(hào)強(qiáng)度。
2.監(jiān)聽當(dāng)前連接
在獲得可用AP列表的基礎(chǔ)上,遍歷當(dāng)前AP,看誰(shuí)正在連接,并取得它的信號(hào)。代碼片段如下:
bool isConnect = false; int numberOfItems = pWLAN_AVAILABLE_NETWORK_LIST->dwNumberOfItems; for(int i = 0; i <= numberOfItems; i++) { WLAN_AVAILABLE_NETWORK wlanAN = pWLAN_AVAILABLE_NETWORK_LIST->Network[i]; if(wlanAN.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) { Wprintf(WLAN signal is %s:%d\n", wlanAN.strProfileName, wlanAN.wlanSignalQuality); isConnect = true; } } if(!isConnect){ wprintf("Wifi is disconnected!\n");}
3.斷開連接
如果wifi處于連接狀態(tài),將其斷開。WlanDisconnect還是容易使用的。原型如下:
DWORD WINAPI WlanDisconnect( _In_ HANDLE hClientHandle, _In_ const GUID *pInterfaceGuid, _Reserved_ PVOID pReserved );
代碼演示在后面。
4.連接一個(gè)有profile的AP(已保存過(guò)密碼)
這是本文的重點(diǎn)。
雖然連接函數(shù)WlanConnect原型很簡(jiǎn)單:
DWORD WINAPI WlanConnect( _In_ HANDLE hClientHandle, _In_ const GUID *pInterfaceGuid, _In_ const PWLAN_CONNECTION_PARAMETERS pConnectionParameters, _Reserved_ PVOID pReserved );
還好我的需求還是蠻簡(jiǎn)單的,只要連接已有的profile的AP。那么我的工作就會(huì)有針對(duì)性的開展。挫折了好多天,每次都連接失敗,原因是ERROR_INVALID_PARAMETER。
就在今天,我終于成功了。真是會(huì)者不難,難者不會(huì)啊。
看看連接參數(shù)的結(jié)構(gòu)體:
typedef struct _WLAN_CONNECTION_PARAMETERS { WLAN_CONNECTION_MODE wlanConnectionMode; LPCWSTR strProfile; PDOT11_SSID pDot11Ssid; PDOT11_BSSID_LIST pDesiredBssidList; DOT11_BSS_TYPE dot11BssType; DWORD dwFlags; } WLAN_CONNECTION_PARAMETERS, *PWLAN_CONNECTION_PARAMETERS;
為了實(shí)現(xiàn)我的要求,可以這樣賦值:
wlanConnectionMode這里設(shè)成wlan_connection_mode_profile;
strProfile寫上你要連接ap的名稱(通常是profile名稱);
pDot11Ssid用不上,設(shè)置NULL;
pDesiredBssidList同樣置成NULL;
dot11BssType我給設(shè)成dot11_BSS_type_infrastructure(基礎(chǔ)設(shè)施?);
dwFlags設(shè)置為WLAN_CONNECTION_HIDDEN_NETWORK。
確實(shí)是工作了,strProfile如何獲取呢?參見監(jiān)聽連接信號(hào)中對(duì)可用AP列表中第一個(gè)profile的獲取。
完整代碼如下:
// #include "stdafx.h" #include <windows.h> #include <wlanapi.h> #include <objbase.h> #include <wtypes.h> #include <string> #include <stdio.h> #include <stdlib.h> // Need to link with Wlanapi.lib and Ole32.lib #pragma comment(lib, "wlanapi.lib") #pragma comment(lib, "ole32.lib") using namespace std; int listenStatus() { HANDLE hClient = NULL; DWORD dwMaxClient = 2; DWORD dwCurVersion = 0; DWORD dwResult = 0; DWORD dwRetVal = 0; int iRet = 0; WCHAR GuidString[39] = {0}; //Listen the status of the AP you connected. while(1){ Sleep(5000); PWLAN_INTERFACE_INFO_LIST pIfList = NULL;//I think wlan interface means network card PWLAN_INTERFACE_INFO pIfInfo = NULL; DWORD dwFlags = 0; dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult); return 1; } dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult); return 1; } else { wprintf(L"WLAN_INTERFACE_INFO_LIST for this system\n"); wprintf(L"Num Entries: %lu\n", pIfList->dwNumberOfItems); wprintf(L"Current Index: %lu\n\n", pIfList->dwIndex); int i; for (i = 0; i < (int) pIfList->dwNumberOfItems; i++) { pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i]; wprintf(L" Interface Index[%u]:\t %lu\n", i, i); iRet = StringFromGUID2(pIfInfo->InterfaceGuid, (LPOLESTR) &GuidString, sizeof(GuidString)/sizeof(*GuidString)); if (iRet == 0) wprintf(L"StringFromGUID2 failed\n"); else { wprintf(L" InterfaceGUID[%d]: %ws\n",i, GuidString); } wprintf(L" Interface Description[%d]: %ws", i, pIfInfo->strInterfaceDescription); wprintf(L"\n"); wprintf(L" Interface State[%d]:\t ", i); switch (pIfInfo->isState) { case wlan_interface_state_not_ready: wprintf(L"Not ready\n"); break; case wlan_interface_state_connected: wprintf(L"Connected\n"); break; case wlan_interface_state_ad_hoc_network_formed: wprintf(L"First node in a ad hoc network\n"); break; case wlan_interface_state_disconnecting: wprintf(L"Disconnecting\n"); break; case wlan_interface_state_disconnected: wprintf(L"Not connected\n"); break; case wlan_interface_state_associating: wprintf(L"Attempting to associate with a network\n"); break; case wlan_interface_state_discovering: wprintf(L"Auto configuration is discovering settings for the network\n"); break; case wlan_interface_state_authenticating: wprintf(L"In process of authenticating\n"); break; default: wprintf(L"Unknown state %ld\n", pIfInfo->isState); break; } } } } } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hClient = NULL; DWORD dwMaxClient = 2; DWORD dwCurVersion = 0; DWORD dwResult = 0; DWORD dwRetVal = 0; int iRet = 0; /* variables used for WlanEnumInterfaces */ PWLAN_INTERFACE_INFO_LIST pIfList = NULL; PWLAN_INTERFACE_INFO pIfInfo = NULL; LPCWSTR pProfileName = NULL; LPWSTR pProfileXml = NULL; DWORD dwFlags = 0; pProfileName = argv[1]; wprintf(L"Information for profile: %ws\n\n", pProfileName); dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult); return 1; } dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult); return 1; } else { dwResult = WlanDisconnect(hClient, &pIfList->InterfaceInfo[0].InterfaceGuid,NULL);//DISCONNECT FIRST if(dwResult != ERROR_SUCCESS) { printf("WlanDisconnect failed with error: %u\n",dwResult); return -1; } PWLAN_AVAILABLE_NETWORK_LIST pWLAN_AVAILABLE_NETWORK_LIST = NULL; dwResult = WlanGetAvailableNetworkList(hClient, &pIfList->InterfaceInfo[0].InterfaceGuid, WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES, NULL, &pWLAN_AVAILABLE_NETWORK_LIST); if (dwResult != ERROR_SUCCESS) { printf("WlanGetAvailableNetworkList failed with error: %u\n",dwResult); WlanFreeMemory(pWLAN_AVAILABLE_NETWORK_LIST); return -1; } WLAN_AVAILABLE_NETWORK wlanAN = pWLAN_AVAILABLE_NETWORK_LIST->Network[0];//PLEASE CHECK THIS YOURSELF if(pProfileName == NULL) pProfileName = wlanAN.strProfileName; WLAN_CONNECTION_PARAMETERS wlanConnPara; wlanConnPara.wlanConnectionMode =wlan_connection_mode_profile ; //YES,WE CONNECT AP VIA THE PROFILE wlanConnPara.strProfile =pProfileName; // set the profile name wlanConnPara.pDot11Ssid = NULL; // SET SSID NULL wlanConnPara.dot11BssType = dot11_BSS_type_infrastructure; //dot11_BSS_type_any,I do not need it this time. wlanConnPara.pDesiredBssidList = NULL; // the desired BSSID list is empty wlanConnPara.dwFlags = WLAN_CONNECTION_HIDDEN_NETWORK; //it works on my WIN7\8 dwResult=WlanConnect(hClient,&pIfList->InterfaceInfo[0].InterfaceGuid,&wlanConnPara ,NULL); if (dwResult==ERROR_SUCCESS) { printf("WlanConnect success!\n"); } else { printf("WlanConnect failed err is %d\n",dwResult); } } listenStatus(); //LISTEN THE STATUS if (pProfileXml != NULL) { WlanFreeMemory(pProfileXml); pProfileXml = NULL; } if (pIfList != NULL) { WlanFreeMemory(pIfList); pIfList = NULL; } return dwRetVal; }
5.打開網(wǎng)絡(luò)設(shè)置界面
遇到以前沒(méi)有連接過(guò)的AP,需要輸入密碼,那么,直接打開配置界面讓用戶自己來(lái)搞吧。
ShellExecute( NULL, L"open", L"shell:::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{38a98528-6cbf-4ca9-8dc0-b1e1d10f7b1b}", NULL, NULL, SW_SHOWNORMAL);
6.RSSI
當(dāng)屏幕上打印出“WlanConnect success!”的時(shí)候,別提多高興了。
就像愛(ài)迪生試驗(yàn)燈絲一下,在無(wú)數(shù)次失敗后,終于找到了一種材料可以勝任燈絲的工作。這種喜悅真的令人振奮,往日的陰霾和不爽終于一掃而光。
其實(shí)我也嘗試過(guò)WlanGetProfile和WlanSetProfile,雖然有時(shí)結(jié)果是能夠連上指定AP,但是函數(shù)返回結(jié)果卻總是ERROR_INVALID_PARAMETER。
網(wǎng)上的例子,很多都是抄來(lái)抄去的,寫的不明不白,雖然有過(guò)幫助,但是也有些誤導(dǎo)。
今天自己成功的連接到指定AP了(用命令行運(yùn)行我的例子,輸入?yún)?shù)profile name),我一定要把它發(fā)表出來(lái),讓其他人有個(gè)參考。
我認(rèn)為這是一件誠(chéng)意的作品,在此也謝謝給過(guò)我?guī)椭呐笥选?br />
最后說(shuō)一下獲得的信號(hào)。標(biāo)準(zhǔn)信號(hào)RSSI是負(fù)值,而這里獲得的信號(hào)都是正值(0~100),在有些需要RSSI的地方,我們需要轉(zhuǎn)換一下:
if (pBssEntry->wlanSignalQuality == 0) iRSSI = -100; else if (pBssEntry->wlanSignalQuality == 100) iRSSI = -50; else iRSSI = -100 + (pBssEntry->wlanSignalQuality/2); wprintf(L" Signal Quality[%u]:\t %u (RSSI: %i dBm)\n", j, pBssEntry->wlanSignalQuality, iRSSI);
7.Wifi on與wifi off
下面要說(shuō)的是在軟件層面控制無(wú)線網(wǎng)卡的開和關(guān)。
問(wèn)題聽起來(lái)簡(jiǎn)單,調(diào)查起來(lái)復(fù)雜,但解決起來(lái)卻也簡(jiǎn)單。關(guān)鍵函數(shù)便是Native wifi api中的WlanSetInterface。其實(shí)這個(gè)API功能也是非
常強(qiáng)大的,我只用到其中控制wifi radio state的功能。官網(wǎng)文檔在此。
函數(shù)原型:
DWORD WINAPI WlanSetInterface( _In_ HANDLE hClientHandle, _In_ const GUID *pInterfaceGuid, _In_ WLAN_INTF_OPCODE OpCode, _In_ DWORD dwDataSize, _In_ const PVOID pData, _Reserved_ PVOID pReserved );
重點(diǎn)說(shuō)一下三個(gè)參數(shù):
(1) OpCode,指定要設(shè)置的參數(shù)。我們選擇wlan_intf_opcode_radio_state
(2) DwDataSize,pData的size。傳入時(shí)用sizeof得到。
(3) pData,radio state對(duì)應(yīng)的data是WLAN_PHY_RADIO_STATE。
看看這個(gè)state結(jié)構(gòu)體:
typedef struct _WLAN_PHY_RADIO_STATE { DWORD dwPhyIndex; DOT11_RADIO_STATE dot11SoftwareRadioState; DOT11_RADIO_STATE dot11HardwareRadioState; } WLAN_PHY_RADIO_STATE, *PWLAN_PHY_RADIO_STATE;
Index設(shè)為0.
State設(shè)置如下:
typedef enum _DOT11_RADIO_STATE { dot11_radio_state_unknown, dot11_radio_state_on, dot11_radio_state_off } DOT11_RADIO_STATE, *PDOT11_RADIO_STATE;
與前幾個(gè)API(比如wlanconnect)相比,這個(gè)函數(shù)的使用簡(jiǎn)單多了。全部源碼如下:
// ManageWirelessNetwork.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdio.h> #include <windows.h> #include <shellapi.h> #include <wlanapi.h> // Need to link with shell32.lib #pragma comment(lib, "shell32.lib") #pragma comment(lib, "wlanapi.lib") int _tmain(int argc, _TCHAR* argv[]) { DWORD dwResult = 0; DWORD dwMaxClient = 2; DWORD dwCurVersion = 0; HANDLE hClient = NULL; PWLAN_INTERFACE_INFO_LIST pIfList = NULL; PWLAN_INTERFACE_INFO pIfInfo = NULL; dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult); return false; } dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult); return false; } WLAN_PHY_RADIO_STATE state; state.dwPhyIndex = 0; state.dot11SoftwareRadioState = dot11_radio_state_on; PVOID pData = &state; dwResult = WlanSetInterface(hClient,&pIfList->InterfaceInfo[0].InterfaceGuid, wlan_intf_opcode_radio_state,sizeof(WLAN_PHY_RADIO_STATE),pData,NULL); if(dwResult == ERROR_SUCCESS) { wprintf(L"set state success!\n"); } else { wprintf(L"set state failed!err is %d\n",dwResult); } return 0; }
8.GOTO在釋放資源時(shí)的作用
GOTO語(yǔ)句有著很臭的名聲,我們的老師經(jīng)常教導(dǎo)我們說(shuō),不要輕易使用它。
C++跳轉(zhuǎn)語(yǔ)句有三個(gè):goto、break和continue。它們只是工具,我覺(jué)得問(wèn)題不能歸咎于工具,問(wèn)題在于人。
就像指針一樣,goto這個(gè)無(wú)條件跳轉(zhuǎn)語(yǔ)句力量還是很強(qiáng)大的,如果濫用,出現(xiàn)問(wèn)題很難排查。
但有些時(shí)候goto確實(shí)是不二選擇,例如我遇到的,在函數(shù)中有多個(gè)出口,而每個(gè)出口都遇到釋放資源的時(shí)候,與其都把釋放語(yǔ)句不厭其煩的寫一遍,
不如一個(gè)goto語(yǔ)句來(lái)的干脆利落。
下面的例子取自上一篇Native Wifi API文章,由于我們的程序經(jīng)??刂频膚ifi的on和off,必須注意釋放資源。就拿WlanOpenHandle來(lái)說(shuō),
如果不注意對(duì)稱WlanCloseHandler,程序幾次運(yùn)行后報(bào)錯(cuò):ERROR_REMOTE_SESSION_LIMIT_EXCEEDED
官網(wǎng)解釋為:Too many handles have been issued by the server.
所以我們會(huì)在每個(gè)API調(diào)用后,確認(rèn)返回值,如果錯(cuò)誤,程序?qū)⒉辉倮^續(xù)向下運(yùn)行,return之前,我們必須釋放資源。當(dāng)出口很多時(shí),我們要寫很多同樣的代碼,
很煩躁,難讀,代碼急速膨脹。但使用goto后,問(wèn)題便輕松了許多,請(qǐng)看簡(jiǎn)單例子:
// ManageWirelessNetwork.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdio.h> #include <windows.h> #include <shellapi.h> #include <wlanapi.h> // Need to link with shell32.lib #pragma comment(lib, "shell32.lib") #pragma comment(lib, "wlanapi.lib") int _tmain(int argc, _TCHAR* argv[]) { DWORD dwResult = 0; DWORD dwMaxClient = 2; DWORD dwCurVersion = 0; HANDLE hClient = NULL; PWLAN_INTERFACE_INFO_LIST pIfList = NULL; PWLAN_INTERFACE_INFO pIfInfo = NULL; dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult); return false; } dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult); goto RELEASE_RESOURCE; } WLAN_PHY_RADIO_STATE state; state.dwPhyIndex = 0; state.dot11SoftwareRadioState = dot11_radio_state_on;//off here too. PVOID pData = &state; dwResult = WlanSetInterface(hClient,&pIfList->InterfaceInfo[0].InterfaceGuid, wlan_intf_opcode_radio_state,sizeof(WLAN_PHY_RADIO_STATE),pData,NULL); if(dwResult == ERROR_SUCCESS) { wprintf(L"set state success!\n"); } else { wprintf(L"set state failed!err is %d\n",dwResult); } RELEASE_RESOURCE: if(hClient) { WlanCloseHandle(hClient,NULL); hClient = NULL; } if(pIfList) { WlanFreeMemory(pIfList); pIfList = NULL; } if(pIfInfo) { WlanFreeMemory(pIfInfo); pIfInfo = NULL; } return 0; }
最后,goto還會(huì)用來(lái)跳出多重循環(huán)。但需要注意的是,只能從內(nèi)層跳到外層,不可逆操作。
后記:
其實(shí)幾個(gè)月前就要實(shí)現(xiàn)windows上的wifi on和off,問(wèn)了許多人,發(fā)了許多帖子,最后都不了了之。之后的日子里也發(fā)生了許多事。國(guó)內(nèi)的
搜索無(wú)果,加上google的無(wú)法使用,都對(duì)調(diào)查增加了些許難度。我們把重點(diǎn)先放到了native wifi api的幾個(gè)方法,見上一篇玩轉(zhuǎn)文章。但
那并不是我想要的。
原以為windows也會(huì)想android一樣,普通應(yīng)用沒(méi)有權(quán)限來(lái)控制wifi的開關(guān)呢,結(jié)果并不是這樣。這也宣告了之前我的判斷失誤。
直到今天,通過(guò)Bing發(fā)現(xiàn)了幾條線索。那是通過(guò)C#調(diào)用native wifi api的問(wèn)題,里面提及了之前并沒(méi)有重視的wlansetinterface。
Interface,在這里我覺(jué)得可以理解成無(wú)線網(wǎng)卡。類似的WlanEnumInterfaces中實(shí)現(xiàn)的功能是羅列出當(dāng)前無(wú)線網(wǎng)卡。
無(wú)線網(wǎng)卡的設(shè)置,其中有一項(xiàng)是radio的狀態(tài)。
果然,這一切都有了了斷。
相關(guān)文章
C語(yǔ)言中g(shù)etchar()的返回類型為什么是int詳解
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中g(shù)etchar()的返回類型為什么是int的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11C++ Log日志類輕量級(jí)支持格式化輸出變量實(shí)現(xiàn)代碼
這篇文章主要介紹了C++ Log日志類輕量級(jí)支持格式化輸出變量實(shí)現(xiàn)代碼,需要的朋友可以參考下2019-04-04C++中的按位與&、按位與或|、按位異或^運(yùn)算符詳解
這篇文章主要介紹了C++中的按位與&、按位與或|、按位異或^運(yùn)算符,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-01-01C++?vector與數(shù)組轉(zhuǎn)換寫入/讀出文件方式
這篇文章主要介紹了C++?vector與數(shù)組轉(zhuǎn)換寫入/讀出文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11c語(yǔ)言float類型小數(shù)點(diǎn)后位數(shù)
在本篇文章里小編給大家整理了關(guān)于c語(yǔ)言float類型小數(shù)點(diǎn)后面有幾位的相關(guān)知識(shí)點(diǎn),需要的朋友們可以學(xué)習(xí)下。2020-02-02Qt項(xiàng)目實(shí)戰(zhàn)之實(shí)現(xiàn)MP3音樂(lè)播放器
這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)MP3音樂(lè)播放器,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以了解一下2023-03-03程序員都不知道C語(yǔ)言中的這些小細(xì)節(jié)
本文通過(guò)7到實(shí)例題目給大家展示C語(yǔ)言中的一些小細(xì)節(jié),很少有朋友真正的掌握,感興趣的朋友跟隨小編一起看看吧2021-05-05C++實(shí)現(xiàn)當(dāng)前時(shí)間動(dòng)態(tài)顯示的方法
這篇文章主要介紹了C++實(shí)現(xiàn)當(dāng)前時(shí)間動(dòng)態(tài)顯示的方法,涉及C++時(shí)間操作及Sleep方法的使用,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07