ImGUI 它是与平台无关的C++轻量级跨平台图形界面库,没有任何第三方依赖,可以将ImGUI的源码直接加到项目中使用,该框架通常会配合特定的D3Dx9等图形开发工具包一起使用,ImGUI常用来实现进程内的菜单功能,而有些辅助开发作者也会使用该框架开发菜单页面,总体来说这是一个很不错的绘图库,如下将公开新版ImGUI如何实现绘制外部菜单的功能。

ImGUI官方下载地址:https://github.com/ocornut/imgui/releases

在使用ImGUI页面之前需要先来实现一个简单的附着功能,即如何将一个窗体附着到另一个窗体之上,其实代码很简单,如下所示当用户输入进程PID时,会自动跟随窗体并附着在窗体顶部。

#include <Windows.h>
#include <iostream> struct handle_data
{
unsigned long process_id;
HWND best_handle;
}; // By: LyShark
BOOL IsMainWindow(HWND handle)
{
return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle);
} BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam)
{
// By: LyShark
handle_data& data = *(handle_data*)lParam;
unsigned long process_id = 0;
GetWindowThreadProcessId(handle, &process_id);
if (data.process_id != process_id || !IsMainWindow(handle)) {
return TRUE;
}
data.best_handle = handle;
return FALSE;
} // By: LyShark
HWND FindMainWindow(unsigned long process_id)
{
handle_data data;
data.process_id = process_id;
data.best_handle = 0;
EnumWindows(EnumWindowsCallback, (LPARAM)&data);
return data.best_handle;
} int main(int argc, char* argv[])
{
DWORD pid = 28396; std::cout << "输入进程PID: " << std::endl;
std::cin >> pid; // 获取屏幕宽和高
int iWidth = ::GetSystemMetrics(SM_CXSCREEN);
int iHeight = ::GetSystemMetrics(SM_CYSCREEN); // 根据PID寻找游戏窗口
HWND hwnd = FindMainWindow(pid); while (1)
{
SetTimer(hwnd, 1, 150, NULL); // 实现透明必须设置WS_EX_LAYERED标志
LONG lWinStyleEx = GetWindowLong(hwnd, GWL_EXSTYLE);
lWinStyleEx = lWinStyleEx | WS_EX_LAYERED; SetWindowLong(hwnd, GWL_EXSTYLE, lWinStyleEx);
SetLayeredWindowAttributes(hwnd, 0, RGB(40, 40, 40), LWA_ALPHA); // 去掉标题栏及边框
LONG_PTR Style = GetWindowLongPtr(hwnd, GWL_STYLE);
Style = Style & ~WS_CAPTION & ~WS_SYSMENU & ~WS_SIZEBOX;
SetWindowLongPtr(hwnd, GWL_STYLE, Style); // 至顶层窗口 最大化
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, iWidth, iHeight, SWP_SHOWWINDOW); // 设置窗体可穿透鼠标
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_TRANSPARENT | WS_EX_LAYERED); // 绘图
HDC hdc = ::GetDC(hwnd);
HDC mdc = ::CreateCompatibleDC(hdc); // 创建画笔
HPEN hpen = CreatePen(PS_SOLID, 10, RGB(0, 255, 0));
// DC 选择画笔
SelectObject(hdc, hpen);
// (画笔)从初始点移动到 50,50
MoveToEx(hdc, 100, 100, NULL);
// (画笔)从初始点画线到 100,100
LineTo(hdc, 1000, 1000); RECT rect = {0}; rect.bottom = 10;
rect.left = 20;
rect.right = 20;
rect.top = 15; DrawText(hdc, L"hello lyshark.com", strlen("hello lyshark.com"), &rect, DT_CALCRECT | DT_CENTER | DT_SINGLELINE);
} return 0;
}

绘制效果图:

接着我们使用Imgui绘制一个动态菜单,首先下载imgui并打开项目中的examples目录,找到example_win32_directx9打开后自己配置好dx9SDK开发工具包。

代码直接调用,并附加到Counter-Strike Source游戏窗体之上即可,这段代码也很简单。

#include "imgui.h"
#include "imgui_impl_dx9.h"
#include "imgui_impl_win32.h" #include <d3d9.h>
#include <tchar.h>
#include <iostream> #pragma execution_character_set("utf-8") // 全局变量
// lyshark.com
static HWND hwnd;
static HWND GameHwnd;
static RECT WindowRectangle;
static int WindowWide, WindowHeight; static LPDIRECT3D9 g_pD3D = NULL;
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
static D3DPRESENT_PARAMETERS g_d3dpp = {}; // 单选框设置状态
bool show_another_window = false; // imgui 回调函数
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // By: LyShark
bool CreateDeviceD3D(HWND hWnd)
{
if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
{
return false;
} ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
g_d3dpp.Windowed = TRUE;
g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
g_d3dpp.EnableAutoDepthStencil = TRUE;
g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; if (g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0)
{
return false;
}
return true;
} void CleanupDeviceD3D()
{
if (g_pd3dDevice)
{
g_pd3dDevice->Release();
g_pd3dDevice = NULL;
} if (g_pD3D)
{
g_pD3D->Release();
g_pD3D = NULL;
}
} void ResetDevice()
{
ImGui_ImplDX9_InvalidateDeviceObjects();
HRESULT hr = g_pd3dDevice->Reset(&g_d3dpp);
if (hr == D3DERR_INVALIDCALL)
{
IM_ASSERT(0);
}
ImGui_ImplDX9_CreateDeviceObjects();
} LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
{
return true;
} switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
{
g_d3dpp.BackBufferWidth = LOWORD(lParam);
g_d3dpp.BackBufferHeight = HIWORD(lParam);
ResetDevice();
}
return 0; case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU)
{
return 0;
}
break; case WM_DESTROY:
PostQuitMessage(0);
return 0;
} return DefWindowProc(hWnd, msg, wParam, lParam);
} // 绘制主方法
// www.cnblogs.com/lyshark
void DrawImGUI()
{
// 启动IMGUI自绘
ImGui_ImplDX9_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame(); static float f = 0.0f;
static int counter = 0;
static char sz[256] = { 0 }; ImGui::Begin("LyShark 辅助GUI主菜单");
ImGui::Text("这是一段测试字符串");
ImGui::Checkbox("弹出子窗口", &show_another_window);
ImGui::SliderFloat("浮点条", &f, 0.0f, 1.0f); ImGui::InputText("输入内容", sz, 256, 0, 0, 0); if (ImGui::Button("点我触发"))
counter++;
ImGui::SameLine();
ImGui::Text("触发次数 = %d", counter); ImGui::Text("当前FPS: %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End(); if (show_another_window)
{
ImGui::Begin("我是子窗体", &show_another_window);
ImGui::Text(" 您好,LyShark !");
if (ImGui::Button("关闭窗体"))
show_another_window = false;
ImGui::End();
}
ImGui::EndFrame();
} // 自身窗口循环事件
void WindowMessageLoop()
{
bool done = false;
while (!done)
{
// 每次都将窗体置顶并跟随游戏窗体移动
GetWindowRect(GameHwnd, &WindowRectangle);
WindowWide = (WindowRectangle.right) - (WindowRectangle.left);
WindowHeight = (WindowRectangle.bottom) - (WindowRectangle.top);
DWORD dwStyle = GetWindowLong(GameHwnd, GWL_STYLE);
if (dwStyle & WS_BORDER)
{
WindowRectangle.top += 23;
WindowHeight -= 23;
} // 跟随窗口移动
MoveWindow(hwnd, WindowRectangle.left + 8, WindowRectangle.top + 8, WindowWide - 11, WindowHeight - 11, true); // 开始消息循环
MSG msg;
while (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
{
done = true;
}
} if (done)
{
break;
} // 开始绘制
DrawImGUI(); g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1.0f, 0); if (g_pd3dDevice->BeginScene() >= 0)
{
ImGui::Render();
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
g_pd3dDevice->EndScene();
} HRESULT result = g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
{
ResetDevice();
}
}
} int main(int argc, char *argv[])
{
// 注册窗体类
WNDCLASSEX wc; // 附加到指定窗体上
wc.cbClsExtra = NULL;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = NULL;
wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.lpszClassName = L" ";
wc.lpszMenuName = L" ";
wc.style = CS_VREDRAW | CS_HREDRAW; RegisterClassEx(&wc); // 得到窗口句柄
GameHwnd = FindWindowA(NULL, "Counter-Strike Source");
GetWindowRect(GameHwnd, &WindowRectangle);
WindowWide = WindowRectangle.right - WindowRectangle.left;
WindowHeight = WindowRectangle.bottom - WindowRectangle.top; // 创建窗体
hwnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TOOLWINDOW, L" ", L" ", WS_POPUP, 1, 1, WindowWide, WindowHeight, 0, 0, wc.hInstance, 0); // 显示窗口
SetLayeredWindowAttributes(hwnd, 0, RGB(0, 0, 0), LWA_ALPHA);
SetLayeredWindowAttributes(hwnd, 0, RGB(0, 0, 0), LWA_COLORKEY);
ShowWindow(hwnd, SW_SHOW); // 初始化D3D
if (!CreateDeviceD3D(hwnd))
{
CleanupDeviceD3D();
UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
} // 更新窗体
UpdateWindow(hwnd); // 初始化ImGUI
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.Fonts->AddFontFromFileTTF("c:/windows/fonts/simhei.ttf", 13.0f, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); ImGui::StyleColorsDark();
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX9_Init(g_pd3dDevice); // 开始执行绘制循环事件
WindowMessageLoop(); ImGui_ImplDX9_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext(); CleanupDeviceD3D();
DestroyWindow(hwnd);
UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
}

绘制效果如下:

另外,Imgui也支持绘制到整个屏幕上,也可以当作全局GUI界面来使用。

#include "imgui.h"
#include "imgui_impl_dx9.h"
#include "imgui_impl_win32.h" #include <d3d9.h>
#include <tchar.h>
#include <iostream> #pragma execution_character_set("utf-8") // 全局变量
static HWND hwnd;
static HWND GameHwnd;
static RECT WindowRectangle;
static int WindowWide, WindowHeight; static LPDIRECT3D9 g_pD3D = NULL;
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
static D3DPRESENT_PARAMETERS g_d3dpp = {}; // 单选框设置状态
bool show_another_window = false; // imgui 回调函数
// By: LyShark
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); bool CreateDeviceD3D(HWND hWnd)
{
if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
{
return false;
} ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
g_d3dpp.Windowed = TRUE;
g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
g_d3dpp.EnableAutoDepthStencil = TRUE;
g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; if (g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0)
{
return false;
}
return true;
} void CleanupDeviceD3D()
{
if (g_pd3dDevice)
{
g_pd3dDevice->Release();
g_pd3dDevice = NULL;
} if (g_pD3D)
{
g_pD3D->Release();
g_pD3D = NULL;
}
}
// https://www.cnblogs.com/lyshark
void ResetDevice()
{
ImGui_ImplDX9_InvalidateDeviceObjects();
HRESULT hr = g_pd3dDevice->Reset(&g_d3dpp);
if (hr == D3DERR_INVALIDCALL)
{
IM_ASSERT(0);
}
ImGui_ImplDX9_CreateDeviceObjects();
} LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
{
return true;
} switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
{
g_d3dpp.BackBufferWidth = LOWORD(lParam);
g_d3dpp.BackBufferHeight = HIWORD(lParam);
ResetDevice();
}
return 0; case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU)
{
return 0;
}
break; case WM_DESTROY:
PostQuitMessage(0);
return 0;
} return DefWindowProc(hWnd, msg, wParam, lParam);
} // 绘制主方法
// lyshark.com
void DrawImGUI()
{
// 启动IMGUI自绘
ImGui_ImplDX9_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame(); static float f = 0.0f;
static int counter = 0;
static char sz[256] = { 0 }; ImGui::Begin("LyShark 辅助GUI主菜单");
ImGui::Text("这是一段测试字符串");
ImGui::Checkbox("弹出子窗口", &show_another_window);
ImGui::SliderFloat("浮点条", &f, 0.0f, 1.0f); ImGui::InputText("输入内容", sz, 256, 0, 0, 0); if (ImGui::Button("点我触发"))
counter++;
ImGui::SameLine();
ImGui::Text("触发次数 = %d", counter); ImGui::Text("当前FPS: %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End(); if (show_another_window)
{
ImGui::Begin("我是子窗体", &show_another_window);
ImGui::Text(" 您好,LyShark !");
if (ImGui::Button("关闭窗体"))
show_another_window = false;
ImGui::End();
}
ImGui::EndFrame();
} // 自身窗口循环事件
void WindowMessageLoop()
{
bool done = false;
while (!done)
{
// 每次都将窗体置顶并跟随游戏窗体移动
GetWindowRect(GameHwnd, &WindowRectangle);
WindowWide = (WindowRectangle.right) - (WindowRectangle.left);
WindowHeight = (WindowRectangle.bottom) - (WindowRectangle.top);
DWORD dwStyle = GetWindowLong(GameHwnd, GWL_STYLE);
if (dwStyle & WS_BORDER)
{
WindowRectangle.top += 23;
WindowHeight -= 23;
} // 跟随窗口移动
MoveWindow(hwnd, WindowRectangle.left + 8, WindowRectangle.top + 8, WindowWide - 11, WindowHeight - 11, true); // 开始消息循环
MSG msg;
while (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
{
done = true;
}
} if (done)
{
break;
} // 开始绘制
DrawImGUI(); g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1.0f, 0); if (g_pd3dDevice->BeginScene() >= 0)
{
ImGui::Render();
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
g_pd3dDevice->EndScene();
} HRESULT result = g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
{
ResetDevice();
}
}
} int main(int argc, char *argv[])
{
// 注册窗体类
WNDCLASSEX wc; // 附加到整个屏幕上
wc.cbClsExtra = NULL;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = NULL;
wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.lpszClassName = L" ";
wc.lpszMenuName = L" ";
wc.style = CS_VREDRAW | CS_HREDRAW;
::RegisterClassEx(&wc); // 屏幕宽度和高度
WindowWide = GetSystemMetrics(SM_CXSCREEN);
WindowHeight = GetSystemMetrics(SM_CYSCREEN); // 创建窗体
HWND hwnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TOOLWINDOW, L" ", L" ", WS_POPUP, 1, 1, WindowWide, WindowHeight, 0, 0, wc.hInstance, 0); // 显示窗口
SetLayeredWindowAttributes(hwnd, 0, 1.0f, LWA_ALPHA);
SetLayeredWindowAttributes(hwnd, 0, RGB(0, 0, 0), LWA_COLORKEY);
ShowWindow(hwnd, SW_SHOW); // 初始化D3D
if (!CreateDeviceD3D(hwnd))
{
CleanupDeviceD3D();
UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
} // 更新窗体
UpdateWindow(hwnd); // 初始化ImGUI
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.Fonts->AddFontFromFileTTF("c:/windows/fonts/simhei.ttf", 13.0f, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); ImGui::StyleColorsDark();
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX9_Init(g_pd3dDevice); // 开始执行绘制循环事件
WindowMessageLoop(); ImGui_ImplDX9_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext(); CleanupDeviceD3D();
DestroyWindow(hwnd);
UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
}

绘制效果如下:

ImGUI 1.87 绘制D3D外部菜单的更多相关文章

  1. Revit中绘制带坡度管道

    激活管道绘制命令出现绘制管道上下文菜单,可以根据需要设置管道坡度值,是向上坡度还是向下坡度,其中两个命令非常有用,一个是继承高程,一个是忽略坡度以连接.在Revit建模中尝尝碰到一些带有坡度的管道,比 ...

  2. Delphi如何在Form的标题栏绘制自定义文字

    Delphi中Form窗体的标题被设计成绘制在系统菜单的旁边,如果你想要在标题栏绘制自定义文本又不想改变Caption属性,你需要处理特定的Windows消息:WM_NCPAINT.. WM_NCPA ...

  3. 一步一步跟我学ImGui.第一讲.配置OpenGl2+ImGui环境

    目录 搭建ImGui例子中的第一个OpenGl2环境 一丶搭建OpenGL2环境 1.下载GLFW库 2.解压GLFW库. 3.将GLFW库拷贝到你的工程文件下. 4.配置到Vs2013中. 5.测试 ...

  4. 如何在ChemDraw 15.1 Pro中添加模板

    ChemDraw化学绘图工具为了方便用户的使用,特地开发了众多的各种类型模板.用户在绘制一些简单或复杂的化学结构式时,可以直接从ChemDraw模板库里直接调用使用,虽然ChemDraw模板非常的丰富 ...

  5. 前端之JQuery:JQuery扩展和事件

    jQuery之jQuery扩展和事件 一.jQuery事件 常用事件 blur([[data],fn]) 失去焦点 focus([[data],fn]) 获取焦点( 搜索框例子) change([[d ...

  6. HTML5 中的 canvas 画布(二)

    绘制图片 一.绘制图片 context.drawImage()(即把图片放到canvas里) var image = new Image();  // 先创建图片对象 image.src = '图片的 ...

  7. 翻译:常见问题——ABAP Development Tools for Eclipse

    ABAP Development Tools for Eclipse(简称ADT)是一个基于Eclipse的全新ABAP IDE,这篇文档试图回答有关ADT的最重要的常见问题.这只是一个开始,如果你对 ...

  8. 【CityHunter】游戏进度总控,及需求设计

    需求列表 序号 标题 描述 进度 更新日期 1 游戏主界面 游戏进入的主操作界面,     2 基础定位功能 实现自身定位功能,     3 特殊地点的Marker 搜索周边银行(资产保护).医院(状 ...

  9. DrawableLayout

    提供一个在窗口顶层显示,可从窗口边缘拖出的container组件. DrawableLayout本身作为整个容器,先进行默认显示内容的布局,再进行拖出菜单的内容布局.也就是一个DL包含两个或三个子控件 ...

随机推荐

  1. 如何在CentOS上找出逐渐耗尽磁盘空间的目录和文件

    起因 随着系统运行,CentOS空间不断减少,对此非常焦虑,到底磁盘空间被哪些新增文件占用了呢? 分析过程,主要使用du命令,逐层找出消耗空间的目录 1.在根目录下检索一下文件的占用情况,执行du命令 ...

  2. get 和 post 的区别

    1. get 提交的信息显示在地址栏中 post 提交的信息不显示在地址栏中 2. get 对于敏感数据信息不安全,因为信息显示在地址栏中 post 对于敏感数据安全 3. get 不支持大数据量请求 ...

  3. Element 2 组件源码剖析之布局容器

    0x00 简介 前文分析过组件的 布局栅格化(Grid Layout) ,通过基础的 24 分栏,迅速简便地创建布局. 本文将介绍用于布局的容器组件,使用 Flexbox 功能将其所控制区域设定为特定 ...

  4. PHP memcache add replace set的区别和其他用法收集

    add replace set的区别 最近在面试时遇到一个问题 memcache 的add replace set的区别,故在此进行加强 add 是向服务器添加一个缓存的数据,当该键已存在会返回一个f ...

  5. JavaScript数组方法总结,本文是根据数组原型上的方法进行总结,由于方法太多将会分篇章发布

    通过浏览器控制台 console 可查看到 Array 数组上原型的所有方法(如下图).对于原型问题此文章暂不过多叙述,单针对对象中的方法进行自我看法的总结:细心的同学可以发现对象原型上所携带的方法基 ...

  6. 基于vue2.0原理-自己实现MVVM框架之computed计算属性

    基于上一篇data的双向绑定,这一篇来聊聊computed的实现原理及自己实现计算属性. 一.先聊下Computed的用法 写一个最简单的小demo,展示用户的名字和年龄,代码如下: <body ...

  7. 开源风吹动开源心 ~ 8月16日,你若来,我们(Apache)在等你!

    点击上方蓝字关注ALC Beijing 抢! 太好看了吧! 买它,就是它,买它! 要抢! ALC是Apache Local Community的缩写,是全世界范围的 Apache 开源爱好者本地群组. ...

  8. 成为 Apache 贡献者,从提交第一个简单 PR 开始!

    开源之路,PR 走起 ! ---全球最大同性交友社区 1 fork 以下实例以 incubator-dolphinscheduler 海豚调度为例进行操作 从远端仓库* https://github. ...

  9. mybatis 07: sql标签中 "#{}" 和 "${}" 的作用和比较

    "#{}"占位符 作用 传参大部分使用"#{}",在数据库底层使用的是:PreparedStatement预编译处理对象 数据库底层被解析为"?&qu ...

  10. Git 03 理论

    参考源 https://www.bilibili.com/video/BV1FE411P7B3?spm_id_from=333.999.0.0 版本 本文章基于 Git 2.35.1.2 四个区域 G ...