本文章適合有一定win32基礎(chǔ)的人,此項(xiàng)目在Windows7及以下系統(tǒng)運(yùn)行時(shí)可能會(huì)失敗
成都創(chuàng)新互聯(lián)專(zhuān)注于金州網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供金州營(yíng)銷(xiāo)型網(wǎng)站建設(shè),金州網(wǎng)站制作、金州網(wǎng)頁(yè)設(shè)計(jì)、金州網(wǎng)站官網(wǎng)定制、微信小程序開(kāi)發(fā)服務(wù),打造金州網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供金州網(wǎng)站排名全網(wǎng)營(yíng)銷(xiāo)落地服務(wù)。前言分層窗口雖然對(duì)于大部分人來(lái)說(shuō)比較生僻,但它的功能卻非常強(qiáng)大,能輕易實(shí)現(xiàn)一些比較漂亮的UI界面。
UpdateLayeredWindow函數(shù)UpdateLayeredWindow 函數(shù)?的作用是更新一個(gè)分層窗口,是分層窗口的核心,它的定義如下
//更新分層窗口的位置、大小、形狀、內(nèi)容和透明度
BOOL UpdateLayeredWindow(
[in] HWND hWnd,
[in, optional] HDC hdcDst,
[in, optional] POINT *pptDst,
[in, optional] SIZE *psize,
[in, optional] HDC hdcSrc,
[in, optional] POINT *pptSrc,
[in] COLORREF crKey,
[in, optional] BLENDFUNCTION *pblend,
[in] DWORD dwFlags
);
hWnd:分層窗口的句柄
hdcDst:屏幕 DC 的句柄
pptDst:分層窗口的位置
psize:分層窗口的新大小
hdcSrc:分層窗口的圖面 DC 的句柄
pptSrc:指定層在設(shè)備上下文中的位置
crKey:指定要在組合分層窗口時(shí)使用的顏色鍵
pblend:指定要在組合分層窗口時(shí)使用的透明度值
dwFlags:此參數(shù)的取值可為下列值之一:
值 | 含義 |
---|---|
ULW_ALPHA 0x00000002 | 使用?pblend作為混合函數(shù)。 如果顯示模式為 256 種或更少顏色,則此值的效果與?ULW_OPAQUE的效果相同。 |
ULW_COLORKEY 0x00000001 | 使用?crKey作為透明度顏色。 |
ULW_OPAQUE 0x00000004 | 繪制不透明的分層窗口。 |
ULW_EX_NORESIZE 0x00000008 | 如果當(dāng)前窗口大小與?psize中指定的大小不匹配,則強(qiáng)制?UpdateLayeredWindowIndirect?函數(shù)失敗。 |
如果沒(méi)看懂沒(méi)關(guān)系,下面舉例子時(shí)就明白了。
我們不妨按試試去填寫(xiě)這個(gè)函數(shù):首先需要一個(gè)分層窗口,為了方便我們可以先創(chuàng)建一個(gè)簡(jiǎn)單的win32窗口
#include//注冊(cè)窗口
void RegWindow(HINSTANCE hInstance, LPCWSTR lpClassName, WNDPROC wndProc, DWORD dwColor)
{
WNDCLASS wnd;
wnd.cbClsExtra = 0;
wnd.cbWndExtra = 0;
wnd.hbrBackground = (HBRUSH)(GetStockObject(dwColor));
wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
wnd.hIcon = LoadCursor(NULL, IDI_APPLICATION);
wnd.lpfnWndProc = wndProc;
wnd.lpszClassName = lpClassName;
wnd.lpszMenuName = NULL;
wnd.style = CS_HREDRAW;
wnd.hInstance = hInstance;
RegisterClass(&wnd);
}
//窗口過(guò)程函數(shù)
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg,
WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE PrevhInstance, LPSTR lpCmdLine, int nCmdShow)
{
//注冊(cè)窗口 指定背景為白色
RegWindow(hInstance, L"WINDOW", WindowProc, WHITE_BRUSH);
//創(chuàng)建窗口
HWND hWnd = CreateWindow(L"WINDOW", 0,
WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL);
// 寬 高
//顯示窗口
ShowWindow(hWnd, SW_SHOW);
//更新窗口
UpdateWindow(hWnd);
//消息循環(huán)
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
這樣我們就創(chuàng)建了一個(gè)寬和高為300,背景為白色的普通窗口(左上角圖標(biāo)為本機(jī)鼠標(biāo))
?
接下來(lái)就是創(chuàng)建一個(gè)分層窗口,為了方便,可以直接在消息循環(huán)前創(chuàng)建。
創(chuàng)建分層窗口要用?CreateWindowExW 函數(shù)?,比較簡(jiǎn)單,直接上代碼
...
//更新窗口
UpdateWindow(hWnd);
//創(chuàng)建分層窗口//
//注冊(cè)分層窗口
RegWindow(hInstance, L"LayeredWindow", WindowProc, BLACK_BRUSH);
//創(chuàng)建分層窗口
HWND hLayeredWindow = CreateWindowEx(WS_EX_LAYERED, L"LayeredWindow", 0,
WS_POPUP | WS_BORDER, 0, 0, 100, 100, NULL, NULL, hInstance, NULL);
//將分層窗口設(shè)為本窗口的子窗口
SetParent(hLayeredWindow, hWnd);
//消息循環(huán)
MSG msg;
...
這樣就創(chuàng)建了一個(gè)寬和高為100,背景為黑色的普通窗口。
但運(yùn)行程序后會(huì)發(fā)現(xiàn)并沒(méi)有什么黑色窗口,這是因?yàn)楦路謱哟翱谛枰玫暮瘮?shù)是UpdateLayeredWindow函數(shù),現(xiàn)在應(yīng)該考慮怎么使用這個(gè)函數(shù)了。
...
//將分層窗口設(shè)為本窗口的子窗口
SetParent(hLayeredWindow, hWnd);
//更新分層窗口//
//創(chuàng)建分層窗口的DC
HDC hLayeredWindowDC = GetDC(hLayeredWindow);
HDC hCompatibleDC = CreateCompatibleDC(hLayeredWindowDC);
//填充BLENDFUNCTION結(jié)構(gòu)
BLENDFUNCTION blend = { 0 };
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
//控制顯示位置
POINT ptDst = { 0, 0 };
//控制窗口大小
SIZE sizeWnd = { 100, 100 };
//為0就行
POINT pSrc = { 0, 0 };
//更新分層窗口
UpdateLayeredWindow(hLayeredWindow, hLayeredWindowDC, &ptDst, &sizeWnd, hCompatibleDC, &pSrc, NULL, &blend, ULW_ALPHA);
//釋放DC
DeleteDC(hLayeredWindowDC);
DeleteDC(hCompatibleDC);
//消息循環(huán)
MSG msg;
...
它的第一個(gè)和第二個(gè)參數(shù)很簡(jiǎn)單,只需要填分層窗口的句柄和對(duì)應(yīng)的DC就行了,對(duì)應(yīng)的DC可以用GetDC函數(shù) 獲取。第三個(gè)參數(shù)控制分層窗口顯示位置,第四個(gè)參數(shù)控制分層窗口大小,第五個(gè)參數(shù)為用?CreateCompatibleDC 函數(shù)?獲取的DC,第六個(gè)一般情況下填為零的POINT結(jié)構(gòu),第七個(gè)為NULL就行,第八個(gè)填?BLENDFUNCTION 結(jié)構(gòu)?比較簡(jiǎn)單,最后一個(gè)參數(shù)填ULW_ALPHA,使窗口能設(shè)置透明度。
運(yùn)行程序后發(fā)現(xiàn)窗口上并未出現(xiàn)一個(gè)黑色窗口,我們可以用?GetLastError 函數(shù)?查看錯(cuò)誤代碼。
...
//為0就行
POINT pSrc = { 0, 0 };
//更新分層窗口
int e1 = GetLastError();
UpdateLayeredWindow(hLayeredWindow, hLayeredWindowDC, &ptDst, &sizeWnd, hCompatibleDC, &pSrc, NULL, &blend, ULW_ALPHA);
int e2 = GetLastError();
//釋放DC
DeleteDC(hLayeredWindowDC);
...
如果編寫(xiě)代碼用的是visual studio,可以按f9打斷點(diǎn)從而查看,也可以使用printf打印錯(cuò)誤代碼,要在win32窗口程序中顯示cmd可以參考?在Win32應(yīng)用程序中顯示命令提示符(CMD)
運(yùn)行程序后可以發(fā)現(xiàn)e1的值為0,就可以排除在更新分層窗口前發(fā)生錯(cuò)誤的可能,e2的值為31,意為“連到系統(tǒng)上的設(shè)備沒(méi)有發(fā)揮作用”
SetDIBits函數(shù)為了解決上述問(wèn)題,需要使用?setDIBits 函數(shù)?設(shè)置像素,它的定義如下
int SetDIBits(
[in] HDC hdc,
[in] HBITMAP hbm,
[in] UINT start,
[in] UINT cLines,
[in] const VOID *lpBits,
[in] const BITMAPINFO *lpbmi,
[in] UINT ColorUse
);
它的功能是使用指定 DIB 中找到的顏色數(shù)據(jù),在兼容的位圖設(shè)置像素,網(wǎng)上對(duì)于它的介紹很少,介紹內(nèi)容又比較隱晦難懂,一些內(nèi)容看不懂很正常。接下來(lái)我會(huì)通過(guò)我的理解來(lái)介紹它。
它的第一個(gè)參數(shù)是設(shè)備上下文的句柄,但在這個(gè)項(xiàng)目中它似乎并不重要,因?yàn)楫?dāng)我把它設(shè)為NULL時(shí)也能照常顯示出窗口,第二個(gè)參數(shù)是一個(gè)位圖句柄,只需要?jiǎng)?chuàng)建一個(gè)位圖傳進(jìn)去就行了,第三個(gè)參數(shù)一般直接填0就行,第四個(gè)參數(shù)填要顯示的窗口的高度,如果以左上角為原點(diǎn),此值需要為負(fù)數(shù),第五個(gè)參數(shù)是RGB數(shù)組的指針,控制每個(gè)像素的顏色與透明度,第六個(gè)參數(shù)是一個(gè)?BITMAPINFO 結(jié)構(gòu)?里面還有一個(gè)?BITMAPINFOHEADER 結(jié)構(gòu)?都比較簡(jiǎn)單,最后一個(gè)參數(shù)參數(shù)必須是以下值之一
值 | 含義 |
---|---|
DIB_PAL_COLORS | 顏色表包含一個(gè)由 16 位索引組成的數(shù)組,該數(shù)組包含在?由 hdc參數(shù)標(biāo)識(shí)的設(shè)備上下文的邏輯調(diào)色板中 |
DIB_RGB_COLORS | 提供顏色表并包含文本 RGB 值 |
接下來(lái)就可以直接上代碼
...
//為0就行
POINT pSrc = { 0, 0 };
//創(chuàng)建一副與當(dāng)前DC兼容的位圖
HBITMAP hCustomBmp = NULL;
hCustomBmp = CreateCompatibleBitmap(hLayeredWindowDC, 100, 100);
//將hCustomBmp指定到hCompatibleDC中
SelectObject(hCompatibleDC, hCustomBmp);
//填充bmpInfo
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = 100;
bmpInfo.bmiHeader.biHeight = -(int)100;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biBitCount = 32;
//初始化位圖
char* datas = new char[100 * 100 * 4];
ZeroMemory(datas, 100 * 100 * 4);
//填充像素
char* pdata = datas;
for (int i = 0; i< 100; i++)
{
for (int j = 0; j< 100; j++)
{
//順序并不是RGBA,而是BGRA
*pdata = 233; //Blue
*(pdata + 1) = 222; //Ggeen
*(pdata + 2) = 233; //Red
*(pdata + 3) = 233; //Alpha
pdata += 4;
}
}
//使用指定的DIB顏色數(shù)據(jù)來(lái)設(shè)置位圖中的像素
SetDIBits(NULL, hCustomBmp, 0, 100, datas, &bmpInfo, DIB_RGB_COLORS);
//更新分層窗口
...
雖然到現(xiàn)在你也可能不清楚SetDIBits函數(shù)到底是干什么的,但只需要知道它能讓分層窗口顯示出來(lái)就行了
現(xiàn)在運(yùn)行程序就可以看到一個(gè)類(lèi)似粉色的正方形在主窗口上了
這樣就實(shí)現(xiàn)了一個(gè)分層窗口的創(chuàng)建與顯示。
接下來(lái)我們就要開(kāi)始封裝這個(gè)分層窗口的創(chuàng)建與顯示功能,方便創(chuàng)建多個(gè)分層窗口。
HWND CreateLayeredWindow(HINSTANCE hInstance, HWND hWnd, int iWidth, int iHeight, int iPosX, int iPosY, COLORREF* colBGRA)
{
//注冊(cè)分層窗口
RegWindow(hInstance, L"LayeredWindow", WindowProc, BLACK_BRUSH);
//創(chuàng)建分層窗口
HWND hLayeredWindow = CreateWindowEx(WS_EX_LAYERED, L"LayeredWindow", 0,
WS_POPUP | WS_BORDER, 0, 0, iWidth, iHeight, NULL, NULL, hInstance, NULL);
//將分層窗口設(shè)為本窗口的子窗口
SetParent(hLayeredWindow, hWnd);
//更新分層窗口//
//創(chuàng)建分層窗口的DC
HDC hLayeredWindowDC = GetDC(hLayeredWindow);
HDC hCompatibleDC = CreateCompatibleDC(hLayeredWindowDC);
//填充BLENDFUNCTION結(jié)構(gòu)
BLENDFUNCTION blend = { 0 };
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
//控制顯示位置
POINT ptDst = { iPosX, iPosY };
//控制窗口大小
SIZE sizeWnd = { iWidth, iHeight };
//為0就行
POINT pSrc = { 0, 0 };
//創(chuàng)建一副與當(dāng)前DC兼容的位圖
HBITMAP hCustomBmp = NULL;
hCustomBmp = CreateCompatibleBitmap(hLayeredWindowDC, iWidth, iHeight);
//將hCustomBmp指定到hCompatibleDC中
SelectObject(hCompatibleDC, hCustomBmp);
//填充bmpInfo
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = iWidth;
bmpInfo.bmiHeader.biHeight = -iHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biBitCount = 32;
//使用指定的DIB顏色數(shù)據(jù)來(lái)設(shè)置位圖中的像素
SetDIBits(NULL, hCustomBmp, 0, iHeight, colBGRA, &bmpInfo, DIB_RGB_COLORS);
//更新分層窗口
UpdateLayeredWindow(hLayeredWindow, hLayeredWindowDC, &ptDst, &sizeWnd, hCompatibleDC, &pSrc, NULL, &blend, ULW_ALPHA);
//釋放DC
DeleteDC(hLayeredWindowDC);
DeleteDC(hCompatibleDC);
return hLayeredWindow;
}
就算看不懂也沒(méi)關(guān)系,只要會(huì)用就行了
hInstance:實(shí)例句柄
hWnd:主窗口句柄
iWidth/iHeight:窗口寬高
iPosX/iPosY:窗口位置
colBGRA:窗口每個(gè)像素點(diǎn)的信息
RGBA與BGRA因?yàn)橐恍┨匦?,SetDIBits函數(shù)中RGB數(shù)組的指針指向的內(nèi)容順序?yàn)锽GRA而不是RGBA
所以colBGRA內(nèi)容順序必須是BGRA。
如果你到現(xiàn)在都對(duì)RGBA和BGRA感覺(jué)陌生,那么接下來(lái)的例子也許會(huì)讓你恍然大悟
//非win32窗口程序
#includeint main()
{
//COLORREF就是存儲(chǔ)RGBA的數(shù)據(jù)類(lèi)型
//Alpha默認(rèn)為0
//一個(gè)rgb
COLORREF rgb = RGB(1,2,3);
//bgr就是把rgb反過(guò)來(lái)
COLORREF bgr = RGB(3,2,1);
//colBGRA就是一個(gè)COLORREF數(shù)組,存儲(chǔ)多個(gè)像素點(diǎn)的BGRA信息
COLORREF bgr[9];
return 0;
}
如果你到現(xiàn)在都沒(méi)看懂,那我建議先去熟悉一下win32 GDI。
RGB宏明顯不能滿(mǎn)足我們,因?yàn)镽GB宏它無(wú)法改變透明度,所以我們就需要一個(gè)RGBA宏,它的定義如下
#define RGBA(r,g,b,a) (COLORREF)(((BYTE)(r) |((WORD)((BYTE)(g))<< 8)) |(((DWORD)((BYTE)(b))<< 16)) |(((DWORD)((BYTE)(a))<< 24)))
不用去看它的原理,會(huì)用就行。
現(xiàn)在我們就可以試著去使用我們剛才封裝的創(chuàng)建分層窗口函數(shù),也算是展示一遍完整代碼
#include#define RGBA(r,g,b,a) (COLORREF)(((BYTE)(r) |((WORD)((BYTE)(g))<< 8)) |(((DWORD)((BYTE)(b))<< 16)) |(((DWORD)((BYTE)(a))<< 24)))
//窗口過(guò)程函數(shù)
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg,
WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
//注冊(cè)窗口函數(shù)
void RegWindow(HINSTANCE hInstance, LPCWSTR lpClassName, WNDPROC wndProc, DWORD dwColor)
{
WNDCLASS wnd;
wnd.cbClsExtra = 0;
wnd.cbWndExtra = 0;
wnd.hbrBackground = (HBRUSH)(GetStockObject(dwColor));
wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
wnd.hIcon = LoadCursor(NULL, IDI_APPLICATION);
wnd.lpfnWndProc = wndProc;
wnd.lpszClassName = lpClassName;
wnd.lpszMenuName = NULL;
wnd.style = CS_HREDRAW;
wnd.hInstance = hInstance;
RegisterClass(&wnd);
}
//創(chuàng)建分層窗口
HWND CreateLayeredWindow(HINSTANCE hInstance, HWND hWnd, int iWidth, int iHeight, int iPosX, int iPosY, COLORREF* colRGBA)
{
//創(chuàng)建分層窗口//
//注冊(cè)分層窗口
RegWindow(hInstance, L"LayeredWindow", WindowProc, BLACK_BRUSH);
//創(chuàng)建分層窗口
HWND hLayeredWindow = CreateWindowEx(WS_EX_LAYERED, L"LayeredWindow", 0,
WS_POPUP | WS_BORDER, 0, 0, iWidth, iHeight, NULL, NULL, hInstance, NULL);
//將分層窗口設(shè)為本窗口的子窗口
SetParent(hLayeredWindow, hWnd);
//更新分層窗口//
//創(chuàng)建分層窗口的DC
HDC hLayeredWindowDC = GetDC(hLayeredWindow);
HDC hCompatibleDC = CreateCompatibleDC(hLayeredWindowDC);
//填充BLENDFUNCTION結(jié)構(gòu)
BLENDFUNCTION blend = { 0 };
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
//控制顯示位置
POINT ptDst = { iPosX, iPosY };
//控制窗口大小
SIZE sizeWnd = { iWidth, iHeight };
//為0就行
POINT pSrc = { 0, 0 };
//創(chuàng)建一副與當(dāng)前DC兼容的位圖
HBITMAP hCustomBmp = NULL;
hCustomBmp = CreateCompatibleBitmap(hLayeredWindowDC, iWidth, iHeight);
//將hCustomBmp指定到hCompatibleDC中
SelectObject(hCompatibleDC, hCustomBmp);
//填充bmpInfo
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = iWidth;
bmpInfo.bmiHeader.biHeight = -iHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biBitCount = 32;
//使用指定的DIB顏色數(shù)據(jù)來(lái)設(shè)置位圖中的像素
SetDIBits(NULL, hCustomBmp, 0, iHeight, colRGBA, &bmpInfo, DIB_RGB_COLORS);
//更新分層窗口
UpdateLayeredWindow(hLayeredWindow, hLayeredWindowDC, &ptDst, &sizeWnd, hCompatibleDC, &pSrc, NULL, &blend, ULW_ALPHA);
//釋放DC
DeleteDC(hLayeredWindowDC);
DeleteDC(hCompatibleDC);
return hLayeredWindow;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE PrevhInstance, LPSTR lpCmdLine, int nCmdShow)
{
//注冊(cè)窗口
RegWindow(hInstance, L"WINDOW", WindowProc, WHITE_BRUSH);
//創(chuàng)建窗口
HWND hWnd = CreateWindow(L"WINDOW", 0,
WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL);
//顯示窗口
ShowWindow(hWnd, SW_SHOW);
//更新窗口
UpdateWindow(hWnd);
//創(chuàng)建BGRA數(shù)據(jù)
COLORREF* colBGRA = new COLORREF[100*100];
//初始化
ZeroMemory(colBGRA, 100 * 100 * sizeof(COLORREF));
//填充半透明藍(lán)色
for (int i = 0; i< 100*100; i++)
{
//雖然用的是RGBA,但實(shí)際上是BGRA
colBGRA[i] = RGBA(233, 0, 0, 128);
// B G R A
}
//創(chuàng)建分層窗口
HWND hLW = CreateLayeredWindow(hInstance, hWnd, 100, 100, 0, 0, colBGRA);
//消息循環(huán)
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
不出意外的話(huà)效果是這樣
現(xiàn)在已經(jīng)把最最基礎(chǔ)的分層窗口的創(chuàng)建給講完了,接下來(lái)所有操作都是基于本篇完成的。一些比較漂亮的UI實(shí)現(xiàn)就放到下篇文章講吧。
項(xiàng)目連接?github - LayeredWindowDemo
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧