一、常见图形界面框架(DirectUI、GUI)

1.题外话,纯属扯O

举两个常用的开发框架,MFC和Qt Widget里面每个控件都是Window,这是和DirectUI最大的区别。下面简单梳理下这个DirectUI与GUI之前错综复杂的爱恨情仇:

① 在侏罗纪时期,传统的Handle式GUI框架,是由操作系统内核(win32k.sys)直接提供的接口(GDI),采用消息驱动的机制。窗口在Windows 操作系统中可以分为两种类型:一般窗口(Top-level Window)和子窗口(Child Window)。每一个窗口都会有一个系统全局标识符,也就是所谓的窗口句柄,由系统管理,每个窗口都会有独立的操作流程,用于处理消息的消息队列,循环处理系统发过来的窗口消息,例如当鼠标点击一个按钮的时候,操作系统会捕获鼠标消息,发送给对应窗口,通知窗口依据对应操作做出相对应的改变,重新绘制外观,发送一个按钮被点击的事件,也就是到了此时,用户才介入这个过程,进行按钮被点击之后的业务处理,窗口之间经过消息传递,然后经过一系列接口调用,最终反馈给用户呈现,窗口最终归属还是系统资源,用户层面无法窥探内部细节,仅仅是通过提供的接口进行调用操作,主打陪伴。

② 随着第四次科技革命的崛起,某岛核泄漏事件的发展,人们不再满足于单纯的功能界面,一群追求高颜值、高性能、高DIY的用户呐喊 "Please help me",微软推出了DirectUI框架,采用DirectUI开发的应用程序,简单总结来说,就是除了顶级父窗口由操作系统负责,其余所有窗口全部由自己绘制,自己处理消息事件,窗口仅仅相当于一个容器,界面上的元素都属于一个逻辑区域,你问我什么是DirectUI?系统管得了的我要管,系统管不了的我也要管,先绘后渲,随心所欲,这就是DirectUI思想。

二、ImGui基本情况

1.什么是ImGui?

① ImGUI又称为Dear ImGui,它是一个跨平台、无第三方依赖的C++轻量级跨平台图形界面库,在项目中,可以直接引用ImGUI的源码,也可以编译成lib、dll等, ImGUI常使用DirectX或者OpenGL进行界面渲染,优点:性能高,快,实现简单等。缺点:布局有点复杂、字体支持不友好,不能动态加载等.

② 初步总结上面的话,可以大概理解为性能很好,入门简单,精通很难.需要非常熟悉DirectX或者OpenGL.但基础已经可以满足大多数人的需求了.

闲聊:谈谈ImGui与DirectUI之间,有部分相同点,比如依赖DirectX渲染绘制等,但不同点也很明显,ImGui 并不直接依赖于特定的操作系统或图形API,而是通过底层的图形渲染接口来绘制图形。这意味着 ImGui 可以在多个平台(如Windows、Linux、Mac等)和多个图形API(如DirectX、OpenGL、Vulkan等)上使用。在IMGUI中,用户界面每帧都是从代码中绘制的,而不是通过构建和维护UI元素的树形结构。这种即时模式的方法提供了更直接、更灵活的控制权,尤其适用于需要频繁更新和自定义的应用程序。

2.DirectX又是什么东西?

① DirectX 是微软公司开发的一套多媒体编程接口,用于在 Windows 平台上实现硬件加速的图形和音频功能。DirectX 提供了多个组件,其中包括了 Direct2D、Direct3D、DirectSound、DirectInput 等。它们分别用于2D图形渲染、3D图形渲染、音频处理和输入设备管理等领域。...  官话我也就不重复描述了,并非三言两语解释清除,详细了解的可以深度学习这个。

三、简单程序开发

1.开发前的小准备

① 下载 docking imgui 地址: https://github.com/ocornut/imgui/tree/docking

② 使用Visual Studio X创建一个空项目,打开解决方案根目录,创建文件夹,ImGui,Directx,如图所示

③ 打开下载的ImGui-docking压缩包,拷贝根目录如图所示文件,到刚才项目创建的文件夹"ImGui"下;

④ 拷贝***\imgui-docking\backends文件夹下的如图所示文件,至项目根目录文件夹Directx下;

(1

(2

⑤ 拷贝完成后,现有文件夹下文件如下图所示:

2.开始开发,撸起来.

① 创建main.cpp文件,创建基础测试代码,下面代码已经经过初步修改,修改范围:

(1.初始化屏蔽控制台,添加#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )

(2屏蔽Win32窗口,修改::ShowWindow(hwnd, SW_HIDE);

(3.分离绘制,修改,io.ConfigViewportsNoAutoMerge = true;

(4.关闭垂直同步,g_pSwapChain->Present(0, 0);

(5.增加ImGui对汉字的支持,添加 io.Fonts->AddFontFromFileTTF("C:/Windows/Fonts/SimHei.ttf", 14.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());由于ImGui不支持动态加载,由此会引发内存异常的大....

下面代码里面包含了一些常见组件的使用,官方里面也有例子,具体还需要参照Demo程序慢慢学习.

  1 #include "imgui.h"
2 #include "imgui_impl_win32.h"
3 #include "imgui_impl_dx11.h"
4 #include <d3d11.h>
5 #include <tchar.h>
6 #include <random>
7 #include <ctime>
8 #include <iostream>
9 using namespace std;
10
11 #pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )//屏蔽控制台显示,编译后生效.
12
13 // Data
14 static ID3D11Device* g_pd3dDevice = nullptr;
15 static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr;
16 static IDXGISwapChain* g_pSwapChain = nullptr;
17 static UINT g_ResizeWidth = 0, g_ResizeHeight = 0;
18 static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr;
19
20 // 助手函数的声明
21 bool CreateDeviceD3D(HWND hWnd);
22 void CleanupDeviceD3D();
23 void CreateRenderTarget();
24 void CleanupRenderTarget();
25 LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
26
27 std::string string_to_utf8(const std::string& str)
28 {
29 int nwLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
30 wchar_t* pwBuf = new wchar_t[nwLen + 1];
31 memset(pwBuf, 0, nwLen * 2 + 2);
32 MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);
33
34 int nLen = WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
35 char* pBuf = new char[nLen + 1];
36 memset(pBuf, 0, nLen + 1);
37 WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
38
39 std::string ret = pBuf;
40 delete[]pwBuf;
41 delete[]pBuf;
42
43 return ret;
44 }
45
46 int main(int, char**)
47 {
48 // 创建应用程序窗口
49 //ImGui_ImplWin32_EnableDpiAwareness();
50 WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"demo", nullptr };
51 ::RegisterClassExW(&wc);
52 HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"demo", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);
53
54 // 初始化 Direct3D
55 if (!CreateDeviceD3D(hwnd))
56 {
57 CleanupDeviceD3D();
58 ::UnregisterClassW(wc.lpszClassName, wc.hInstance);
59 return 1;
60 }
61
62 // 设置窗口显示模式
63 ::ShowWindow(hwnd, SW_HIDE);
64 ::UpdateWindow(hwnd);
65
66 // 设置ImGui上下文
67 IMGUI_CHECKVERSION();
68 ImGui::CreateContext();
69 ImGuiIO& io = ImGui::GetIO(); (void)io;
70 //取消生成ini文件
71 io.IniFilename = NULL;
72 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // 启用键盘控制
73 io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // 启用游戏板控制
74 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // 启用停靠
75 io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // 启用多视口/平台窗口
76 io.ConfigViewportsNoAutoMerge = true;
77 //io.ConfigViewportsNoTaskBarIcon = true;
78 //io.ConfigViewportsNoDefaultParent = true;
79 //io.ConfigDockingAlwaysTabBar = true;
80 //io.ConfigDockingTransparentPayload = true;
81 //io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts; // FIXME-DPI:实验。这目前没有按预期工作。不要使用用户内应用程序!
82 //io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleViewports; // FIXME-DPI:实验。
83
84 // 设置ImGui风格
85 ImGui::StyleColorsLight();
86
87 // 启用视口后,我们调整WindowRounding/WindowBg,使平台窗口看起来与常规窗口相同。
88
89 ImGuiStyle& style = ImGui::GetStyle();
90 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
91 {
92 style.WindowMinSize = ImVec2(700, 180);
93
94 style.WindowRounding = 10.0f;
95 style.Colors[ImGuiCol_WindowBg].w = 1.0f;
96
97 style.WindowBorderSize = 1.0f;
98 style.FrameBorderSize = 1.0f;
99 style.PopupBorderSize = 1.0f;
100
101 style.WindowPadding = ImVec2(8.0f, 8.0f);
102 style.FramePadding = ImVec2(4.0f, 8.0f);
103 style.PopupBorderSize = 1.0f;
104
105 }
106
107 // 设置平台/渲染器后端
108 ImGui_ImplWin32_Init(hwnd);
109 ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
110
111 //加载字体
112 //-如果没有加载字体,imgui将使用默认字体。您还可以加载多种字体,并使用ImGui::PushFont()/PopFont 选择它们
113 //-AddFontFromFileTTF()将返回ImFont*,因此如果需要在多个字体中选择字体,则可以存储它。
114 //-如果无法加载文件,则函数将返回一个nullptr。请处理应用程序中的这些错误(例如,使用断言,或显示错误并退出)。
115 //-当调用ImFontAtlas::Build()/GetTexDataAsXXXXX()时,字体将以给定的大小光栅化(w/过采样)并存储到纹理中,下面的ImGui_ImplXXXX_NewFrame将调用该纹理。
116 //-在您的imconfig文件中使用“#define IMGUI_ABLE_FREETYPE”可以使用FREETYPE进行更高质量的字体渲染。
117 //-有关更多说明和详细信息,请阅读“docs/FONTS.md”。
118 //-请记住,在C/C++中,如果要在字符串文字中包含反斜杠,则需要写一个双反斜杠\\
119 io.Fonts->AddFontFromFileTTF("C:/Windows/Fonts/SimHei.ttf", 14.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());//支持汉字,单目前Ingui不支持动态,所以在调试模式下启动会变慢,改字体也会占用大量内存.
120
121 // 窗口设置
122 bool show_main_windows = true;
123 bool WindowShouldClose = false;
124
125 ImGui::SetNextWindowSize(ImVec2(700, 180), ImGuiCond_Appearing);
126
127 // 创建计时器变量
128 auto startTime = std::chrono::steady_clock::now();
129 while (!WindowShouldClose)
130 {
131 //轮询和处理消息(输入、窗口大小调整等)
132 //请参阅下面的WndProc()函数,了解如何将事件调度到Win32后端。
133 MSG msg;
134 while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
135 {
136 ::TranslateMessage(&msg);
137 ::DispatchMessage(&msg);
138 if (msg.message == WM_QUIT)
139 WindowShouldClose = true;
140 }
141 if (WindowShouldClose)
142 break;
143
144 //处理窗口大小调整(我们不直接在WM_SIZE处理程序中调整大小)
145 if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
146 {
147 CleanupRenderTarget();
148 g_pSwapChain->ResizeBuffers(0, g_ResizeWidth, g_ResizeHeight, DXGI_FORMAT_UNKNOWN, 0);
149 g_ResizeWidth = g_ResizeHeight = 0;
150 CreateRenderTarget();
151 }
152
153 // 启动ImGui框架
154 ImGui_ImplDX11_NewFrame();
155 ImGui_ImplWin32_NewFrame();
156 ImGui::NewFrame();
157
158 if (show_main_windows)
159 {
160 ImGui::Begin(u8"测试基础客户端", &show_main_windows);
161 std::random_device rd;
162 std::mt19937 gen(rd());
163 std::uniform_real_distribution<float> dis(0.0f, 1.0f);
164 ImVec4 randomColor(dis(gen), dis(gen), dis(gen), 1.0f);
165 ImGui::TextWrapped(u8"****");
166 ImGui::SameLine();
167 ImGui::PushStyleColor(ImGuiCol_Text, randomColor);
168 ImGui::SetCursorPosX((ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(u8"模拟客户端(特效)").x) / 2);
169 ImGui::TextWrapped(u8"模拟客户端(特效)");
170 ImGui::PopStyleColor();
171 ImGui::SameLine();
172 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(u8"****").x);
173 ImGui::TextWrapped(u8"****");
174 ImGui::SeparatorText(u8"画一条分界线");
175
176 ImGui::Text("");
177
178 randomColor.x = 1.0f;
179 randomColor.y = 0.0f;
180 randomColor.z = 1.0f;
181 ImGui::PushStyleColor(ImGuiCol_Text, randomColor);
182 if (GetDriverState())
183 {
184 ImGui::SetCursorPosX((ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(u8"换个颜色").x) / 2);
185 ImGui::TextWrapped(u8"换个颜色");
186 }
187 else
188 {
189 ImGui::SetCursorPosX((ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(u8"再换个颜色·").x) / 2);
190 ImGui::TextWrapped(u8"再换个颜色·");
191 }
192 ImGui::PopStyleColor();
193 ImGui::SeparatorText(u8"");
194
195 // 计算运行时间
196 auto currentTime = std::chrono::steady_clock::now();
197 std::chrono::duration<float> elapsedTime = currentTime - startTime;
198 float runtime = elapsedTime.count();
199
200 // 获取当前时间
201 std::time_t now = std::time(nullptr);
202 std::tm* current_time = std::localtime(&now);
203 static char time_string[64] = { 0 };
204 std::strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", current_time);
205
206 ImGui::TextColored(ImVec4(0.45f, 0.0f, 1.0f, 1.0f), u8"当前时间:%s,软件已运行: %.2f秒.", time_string, runtime);
207 ImGui::End();
208 }
209 else
210 {
211 WindowShouldClose = TRUE;
212 }
213
214 // 渲染页面
215 ImGui::Render();
216 ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
217
218 // 更新和渲染其他平台窗口
219 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
220 {
221 ImGui::UpdatePlatformWindows();
222 ImGui::RenderPlatformWindowsDefault();
223 }
224
225 //g_pSwapChain->Present(1, 0); // 与vsync一起演示
226 g_pSwapChain->Present(0, 0); // 存在但不带vsync
227 }
228
229
230 ImGui_ImplDX11_Shutdown();
231 ImGui_ImplWin32_Shutdown();
232 ImGui::DestroyContext();
233
234 CleanupDeviceD3D();
235 ::DestroyWindow(hwnd);
236 ::UnregisterClassW(wc.lpszClassName, wc.hInstance);
237
238 return 0;
239 }
240
241 // 帮助函数
242 bool CreateDeviceD3D(HWND hWnd)
243 {
244 // 设置交换链
245 DXGI_SWAP_CHAIN_DESC sd;
246 ZeroMemory(&sd, sizeof(sd));
247 sd.BufferCount = 2;
248 sd.BufferDesc.Width = 0;
249 sd.BufferDesc.Height = 0;
250 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
251 sd.BufferDesc.RefreshRate.Numerator = 60;
252 sd.BufferDesc.RefreshRate.Denominator = 1;
253 sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
254 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
255 sd.OutputWindow = hWnd;
256 sd.SampleDesc.Count = 1;
257 sd.SampleDesc.Quality = 0;
258 sd.Windowed = TRUE;
259 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
260
261 UINT createDeviceFlags = 0;
262 //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
263 D3D_FEATURE_LEVEL featureLevel;
264 const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
265 HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
266 if (res == DXGI_ERROR_UNSUPPORTED) // 如果硬件不可用,请尝试高性能的WARP软件驱动程序。
267 res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
268 if (res != S_OK)
269 return false;
270
271 CreateRenderTarget();
272 return true;
273 }
274
275 void CleanupDeviceD3D()
276 {
277 CleanupRenderTarget();
278 if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = nullptr; }
279 if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = nullptr; }
280 if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; }
281 }
282
283 void CreateRenderTarget()
284 {
285 ID3D11Texture2D* pBackBuffer;
286 g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
287 g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_mainRenderTargetView);
288 pBackBuffer->Release();
289 }
290
291 void CleanupRenderTarget()
292 {
293 if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = nullptr; }
294 }
295
296 #ifndef WM_DPICHANGED
297 #define WM_DPICHANGED 0x02E0 // From Windows SDK 8.1+ headers
298 #endif
299
300 // 从imgui_impl_win32.cpp转发声明消息处理程序
301 extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
302
303 //Win32消息处理程序
304 //你可以阅读io.WantCaptureMouse,io.WantCaptureKeyboard标志来判断imgui是否想使用你的输入。
305 //-当io.WantCaptureMouse为true时,不要将鼠标输入数据发送到主应用程序,也不要清除/覆盖鼠标数据的副本。
306 //-当io.WantCaptureKeyboard为true时,不要将键盘输入数据发送到主应用程序,也不要清除/覆盖键盘数据的副本。
307 //通常情况下,您可能总是将所有输入传递给imgui,并根据这两个标志对应用程序隐藏它们。
308 LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
309 {
310 if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
311 return true;
312
313 switch (msg)
314 {
315 case WM_SIZE:
316 if (wParam == SIZE_MINIMIZED)
317 return 0;
318 g_ResizeWidth = (UINT)LOWORD(lParam); // 调整队列大小
319 g_ResizeHeight = (UINT)HIWORD(lParam);
320 return 0;
321 case WM_SYSCOMMAND:
322 if ((wParam & 0xfff0) == SC_KEYMENU) // 禁用ALT应用程序菜单
323 return 0;
324 break;
325 case WM_DESTROY:
326 ::PostQuitMessage(0);
327 return 0;
328 case WM_DPICHANGED:
329 if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
330 {
331 //const int dpi = HIWORD(wParam);
332 //printf("WM_DPICHANGED to %d (%.0f%%)\n", dpi, (float)dpi / 96.0f * 100.0f);
333 const RECT* suggested_rect = (RECT*)lParam;
334 ::SetWindowPos(hWnd, nullptr, suggested_rect->left, suggested_rect->top, suggested_rect->right - suggested_rect->left, suggested_rect->bottom - suggested_rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
335 }
336 break;
337 }
338 return ::DefWindowProcW(hWnd, msg, wParam, lParam);
339 }

② 补齐环境引用,VS右键项目属性:

(1.C++\常规\附加包含目录 添加 .\Imgui;.\Directx;

(2.链接器\输入\依赖性  添加 d3d11.lib;d3dcompiler.lib;dxgi.lib;

3.开发完跑跑试试

① 编译运行,附上效果图(自己改改文字即可实现.):

基于DirectX11+ImGui的Win32桌面程序开发的更多相关文章

  1. 用python进行桌面程序开发

    Python是一种面向对象.直译式计算机程序设计语言,也是一种功能强大而完善的通用型语言,已经具有十多年的发展历史,成熟且稳定.这种语言具有非常简捷而清晰的语法特点,适合完成各种高层任务,几乎可以在所 ...

  2. Python3的桌面程序开发利器:Eric6的环境搭建、使用

    本文旨在通过一个简单的demo,介绍基于Python3.PyQT5的环境下开发桌面应用程序的一种方案,当然开发Python的桌面应用程序不止是PyQT 这一种方案,还可以使用Python自带的Tkin ...

  3. [Flutter] Windows桌面程序开发

    在今年5月的谷歌I/O 2019大会时, 谷歌就宣布了flutter已经支持全平台开发, 包括 android, ios, mac, linux, windows, web 等 . Flutter桌面 ...

  4. 使用 VS2017 和 js 进行桌面程序开发 - electron 之 Hello Word

    现在基于 js 和 web浏览器核心构建的 C/S 程序越来越多,比如微信桌面版(基于 duilib 和 cef).VS CODE(基于electron)等,出于了解的目的,最近学习了 electro ...

  5. 如何选择合适的Linux系统进行桌面程序开发?

    32 or 64 ? 众所周知,64位的Windows系统可以近乎完美地运行32位的应用程序,微软出于商业考虑做了这样一个兼容层.而Linux系统则划分的很清楚,默认情况下64位的Linux系统无法运 ...

  6. 基于go语言结合微信小程序开发的微商城系统

    最近在慕课网上录制了一门<Golang微信小程序微商城系统原型>,这门免费课程特别适合在校大学生或者刚毕业的大学生,go语言初学者以及想要从事微商城开发项目入门的小伙伴们来学习.在课程当中 ...

  7. 实验一:基于Winsock完成简单的网络程序开发

    第一部分:简答的UDP网络通信程序 // UDP5555.cpp : Defines the entry point for the application. //================== ...

  8. 桌面程序开发入门(WinForm with C#)

    1.使用Visual Studio 2013创建新项目 2.创建一个主窗体和4个子窗体 3.创建一个数据库.一个表.一个存储过程 4.在配置文件里添加数据库连接字符串 5.真正的编码工作. 第一步:创 ...

  9. 基于OpenCV的图书扫描识别程序开发

    1.AndroidStudio环境配置 https://www.cnblogs.com/little-monkey/p/7162340.html

  10. win32界面程序开发,自制一个会自动销毁的提示框

    思路:创建线程里面启动窗口,设置定时器关闭该窗口. 创建窗口几个步骤和一般窗口无异,注册.然后createwindow,之后showwinodw,然后消息循环. 在createwindow之后,获取到 ...

随机推荐

  1. 在IIS 搭建FTP站点

    最近在项目中需要用到FTP,需要将生成的文件通过FTP上传网站. 在此记录下. FTP SSL设置,需要允许SSL连接. FTP 身份验证,匿名身份验证需要启用. FTP 授权规则,如果没有特殊情况允 ...

  2. Looper 源码分析

    //可以看到我们的Looper是存放在线程独有的ThreadLocal进行隔离的    //也就是每个线程独有一份Looper    static final ThreadLocal<Loope ...

  3. Linux普通用户使用docker以及docker-compose

    # 添加limstorm普通用户到docker用户组 sudo gpasswd -a limstorm docker # 切换docker用户组,该命令类似login指令,当它是以相同的帐号,另一个群 ...

  4. java项目 学生成绩管理系统 (源码+数据库文件)

    ​ 需要的私信我 备注来意:项目名称 来了就点个赞再走呗,即将毕业的兄弟有福了 文章底部获取源码 java项目  学生成绩管理 (源码+数据库文件)技术框架:java+springboot+vue+m ...

  5. Java SpringBoot 加载 yml 配置文件中字典项

    将字典数据,配置在 yml 文件中,通过加载yml将数据加载到 Map中 Spring Boot 中 yml 配置.引用其它 yml 中的配置.# 在配置文件目录(如:resources)下新建app ...

  6. 04-webpack初体验

    /** * index.js: webpack入口起点文件 * * 1.运行指令: * 开发环境:webpack ./src/index.js -o ./build --mode=developmen ...

  7. This application failed to start because it could not find or load the Qt platforms plugins

     由于一直在linux下操作,今天Qt移植平台的时候导致.exe可执行文件一直运行不起来,提示缺少某些dll库,这个问题解决起来简单(直接去qt源码里面查找对应库添加到可执行文件目录就行),但是之后一 ...

  8. 保姆级教程:用GPU云主机搭建AI大语言模型并用Flask封装成API,实现用户与模型对话

    导读 在当今的人工智能时代,大型AI模型已成为获得人工智能应用程序的关键.但是,这些巨大的模型需要庞大的计算资源和存储空间,因此搭建这些模型并对它们进行交互需要强大的计算能力,这通常需要使用云计算服务 ...

  9. shell基本命令与参数

    1:一行可以有多个命令,用";"分开 如: cd ..; ls -l 2:先项用"-"开始,多个连接可连在一起,如:ls -lh, 3:"--&quo ...

  10. 2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法。 宏使用如下: #[derive(Builder)] pub stru

    2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法. 宏使用如下: #[derive(Builder)] pub stru ...