Windows API 学习~

news/2025/2/26 14:11:54/文章来源:https://www.cnblogs.com/cosyQAQ/p/18738346

用api 创建一个Windows 窗口

windows窗口创建过程

Windows API 索引 - Win32 apps | Microsoft Learn

创建项目

image

配置属性,系统里面子系统选择窗口

image

  1. 注册窗口类: 首先需要调用RegisterClassEx 函数来注册一个窗口类,该函数会向操作系统注册一个新的窗口类, 并返回一个唯一的类标识符, 以供后续创建窗口时使用。在注册窗口类时需要指定窗口的基本属性, 如窗口过程、背景颜色、光标等信息。

  2. 创建窗口: 调用CreateWindowEx函数来创建一 个窗口实例。在创建窗口时需要指定窗口类名称、窗口名称、窗口样式等参数,同时可以设置窗口位置、大小、字体、菜单等属性。

  3. 显示窗口: 调用ShowWindow函数将窗口显示到屏蒂上。该函数可以设置窗口的可见性、最小化、最大化状态等。

  4. 进入消息循环: 通过调用GetMessage或者PeekMessage函数来读取并处理窗口消息队列中的消息。在消息循环中,窗口过程会接收和处理各种与窗口相关的事件,如鼠标点击、键盘输入、窗口移动、大小调整等。

创建一个WinMain.cpp,winMain函数按F1可以查看微软的官方文档,以下代码中的函数也可以F1查看官方文档

语法

int __clrcall WinMain([in]           HINSTANCE hInstance,[in, optional] HINSTANCE hPrevInstance,[in]           LPSTR     lpCmdLine,[in]           int       nShowCmd
);

参数

[in] hInstance

类型:HINSTANCE

应用程序的当前实例的句柄。

[in, optional] hPrevInstance

类型:HINSTANCE

应用程序的上一个实例的句柄。 此参数始终 NULL。 如果需要检测另一个实例是否已存在,请使用 CreateMutex 函数创建唯一命名的互斥体。 即使互斥体已存在,CreateMutex 也会成功,但该函数将返回 ERROR_ALREADY_EXISTS。 这表示应用程序的另一个实例存在,因为它首先创建了互斥体。 但是,恶意用户可以在执行此操作之前创建此互斥体,并阻止应用程序启动。 为防止这种情况,请创建一个随机命名的互斥体并存储该名称,以便它只能由授权用户获取。 或者,可以将文件用于此目的。 若要将应用程序限制为每个用户的一个实例,请在用户的配置文件目录中创建锁定的文件。

[in] lpCmdLine

类型:LPSTR

应用程序的命令行,不包括程序名称。 若要检索整个命令行,请使用 GetCommandLine 函数。

[in] nShowCmd

类型:int

控制窗口的显示方式。 此参数可以是 ShowWindow 函数的 nCmdShow 参数中指定的任何值。

关于树视图控件

树视图控件是一种显示分层项目列表的窗口,例如文档中的标题、索引中的条目或磁盘上的文件和目录。 每个项包含一个标签和一个可选位图图像,且每个项可以有一个与之关联的子项列表。 通过单击某个项目,用户可以展开或折叠相关的子项目列表。

下图显示了一个简单的树形视图控件,其中包含一个根节点、一个展开节点和一个折叠节点。 该控件对选定项目使用一个位图,而对其他项目使用另一个位图。

screen shot showing five nodes in a hierarchy; the text of one node is selected, but nodes are not linked to each other by lines

创建树视图控件后,可以通过向控件发送消息来添加、删除、排列或以其他方式来操作项目。 每条消息都有一个或多个相应的宏,可以使用这些宏来代替显式发送消息。

显示卷路径

以下 C++ 示例演示如何显示每个卷和设备的所有路径。 对于系统中的每个卷,本示例查找卷,获取设备名称,获取该卷的所有路径,并显示路径。

#include <windows.h>
#include <stdio.h>void DisplayVolumePaths(__in PWCHAR VolumeName)
{DWORD  CharCount = MAX_PATH + 1;PWCHAR Names     = NULL;PWCHAR NameIdx   = NULL;BOOL   Success   = FALSE;for (;;) {////  Allocate a buffer to hold the paths.Names = (PWCHAR) new BYTE [CharCount * sizeof(WCHAR)];if ( !Names ) {////  If memory can't be allocated, return.return;}////  Obtain all of the paths//  for this volume.Success = GetVolumePathNamesForVolumeNameW(VolumeName, Names, CharCount, &CharCount);if ( Success ) {break;}if ( GetLastError() != ERROR_MORE_DATA ) {break;}////  Try again with the//  new suggested size.delete [] Names;Names = NULL;}if ( Success ){////  Display the various paths.for ( NameIdx = Names; NameIdx[0] != L'\0'; NameIdx += wcslen(NameIdx) + 1 ) {wprintf(L"  %s", NameIdx);}wprintf(L"\n");}if ( Names != NULL ) {delete [] Names;Names = NULL;}return;
}void __cdecl wmain(void)
{DWORD  CharCount            = 0;WCHAR  DeviceName[MAX_PATH] = L"";DWORD  Error                = ERROR_SUCCESS;HANDLE FindHandle           = INVALID_HANDLE_VALUE;BOOL   Found                = FALSE;size_t Index                = 0;BOOL   Success              = FALSE;WCHAR  VolumeName[MAX_PATH] = L"";////  Enumerate all volumes in the system.FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName));if (FindHandle == INVALID_HANDLE_VALUE){Error = GetLastError();wprintf(L"FindFirstVolumeW failed with error code %d\n", Error);return;}for (;;){////  Skip the \\?\ prefix and remove the trailing backslash.Index = wcslen(VolumeName) - 1;if (VolumeName[0]     != L'\\' ||VolumeName[1]     != L'\\' ||VolumeName[2]     != L'?'  ||VolumeName[3]     != L'\\' ||VolumeName[Index] != L'\\') {Error = ERROR_BAD_PATHNAME;wprintf(L"FindFirstVolumeW/FindNextVolumeW returned a bad path: %s\n", VolumeName);break;}////  QueryDosDeviceW does not allow a trailing backslash,//  so temporarily remove it.VolumeName[Index] = L'\0';CharCount = QueryDosDeviceW(&VolumeName[4], DeviceName, ARRAYSIZE(DeviceName)); VolumeName[Index] = L'\\';if ( CharCount == 0 ) {Error = GetLastError();wprintf(L"QueryDosDeviceW failed with error code %d\n", Error);break;}wprintf(L"\nFound a device:\n %s", DeviceName);wprintf(L"\nVolume name: %s", VolumeName);wprintf(L"\nPaths:");DisplayVolumePaths(VolumeName);////  Move on to the next volume.Success = FindNextVolumeW(FindHandle, VolumeName, ARRAYSIZE(VolumeName));if ( !Success ) {Error = GetLastError();if (Error != ERROR_NO_MORE_FILES) {wprintf(L"FindNextVolumeW failed with error code %d\n", Error);break;}////  Finished iterating//  through all the volumes.Error = ERROR_SUCCESS;break;}}FindVolumeClose(FindHandle);FindHandle = INVALID_HANDLE_VALUE;return;
}

下面是运行应用程序的示例输出。 对于每个卷,输出包括卷设备路径、卷 GUID 路径和驱动器号。

Found a device:\Device\HarddiskVolume2
Volume name: \\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\
Paths:  C:\Found a device:\Device\CdRom0
Volume name: \\?\Volume{4c1b02c4-d990-11dc-99ae-806e6f6e6963}\
Paths:  D:\

列出目录中的文件

以下示例调用 FindFirstFileFindNextFileFindClose 列出指定目录中的文件。

#include <windows.h>
#include <tchar.h> 
#include <stdio.h>
#include <strsafe.h>
#pragma comment(lib, "User32.lib")void DisplayErrorBox(LPTSTR lpszFunction);int _tmain(int argc, TCHAR *argv[])
{WIN32_FIND_DATA ffd;LARGE_INTEGER filesize;TCHAR szDir[MAX_PATH];size_t length_of_arg;HANDLE hFind = INVALID_HANDLE_VALUE;DWORD dwError=0;// If the directory is not specified as a command-line argument,// print usage.if(argc != 2){_tprintf(TEXT("\nUsage: %s <directory name>\n"), argv[0]);return (-1);}// Check that the input path plus 3 is not longer than MAX_PATH.// Three characters are for the "\*" plus NULL appended below.StringCchLength(argv[1], MAX_PATH, &length_of_arg);if (length_of_arg > (MAX_PATH - 3)){_tprintf(TEXT("\nDirectory path is too long.\n"));return (-1);}_tprintf(TEXT("\nTarget directory is %s\n\n"), argv[1]);// Prepare string for use with FindFile functions.  First, copy the// string to a buffer, then append '\*' to the directory name.StringCchCopy(szDir, MAX_PATH, argv[1]);StringCchCat(szDir, MAX_PATH, TEXT("\\*"));// Find the first file in the directory.hFind = FindFirstFile(szDir, &ffd);if (INVALID_HANDLE_VALUE == hFind) {DisplayErrorBox(TEXT("FindFirstFile"));return dwError;} // List all the files in the directory with some info about them.do{if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){_tprintf(TEXT("  %s   <DIR>\n"), ffd.cFileName);}else{filesize.LowPart = ffd.nFileSizeLow;filesize.HighPart = ffd.nFileSizeHigh;_tprintf(TEXT("  %s   %ld bytes\n"), ffd.cFileName, filesize.QuadPart);}}while (FindNextFile(hFind, &ffd) != 0);dwError = GetLastError();if (dwError != ERROR_NO_MORE_FILES) {DisplayErrorBox(TEXT("FindFirstFile"));}FindClose(hFind);return dwError;
}void DisplayErrorBox(LPTSTR lpszFunction) 
{ // Retrieve the system error message for the last-error codeLPVOID lpMsgBuf;LPVOID lpDisplayBuf;DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,NULL,dw,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0, NULL );// Display the error message and clean uplpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR),TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf);LocalFree(lpDisplayBuf);
}

用树视图列出文件夹代码示例:

#include<Windows.h>
#include<windowsx.h>
#include<commctrl.h>
#include <vector>
#include <string>#pragma comment(lib, "Comctl32.lib");
#define BTN_BTN_1 1000
#define BTN_CHECHEBOX_1 2000
#define BTN_RADIO_1 3000
#define ID_EDITCHILD 4000HWND hwndTV{};
HTREEITEM AddItemToTree(HWND hwndTV, LPTSTR lpszItem, int nLevel);/// <summary>
/// path 路径
/// </summary>
std::vector<std::wstring> GetFileList(std::wstring path);void InsrtTree(HTREEITEM hParent, HTREEITEM hInsertAfter,std::wstring name)
{TVINSERTSTRUCT trStruct;trStruct.hParent = hParent;trStruct.hInsertAfter = hInsertAfter;TVITEM tItem;WCHAR namebuf[MAX_PATH]{};tItem.mask = TVIF_TEXT;//tItem.hItem = hParent;tItem.pszText = (LPWSTR)name.c_str();tItem.cchTextMax = name.size() + 1;trStruct.item = tItem;TreeView_InsertItem(hwndTV, &trStruct);
}LRESULT CALLBACK MainWndProc(HWND hwnd,        // handle to windowUINT uMsg,        // message identifierWPARAM wParam,    // first message parameterLPARAM lParam)    // second message parameter
{static HWND hwndEdit;TCHAR lpszLatin[] = L"Lorem ipsum dolor sit amet, consectetur ";switch (uMsg){case WM_CREATE://hwndEdit = CreateWindowEx(//    0, L"EDIT",   // predefined class //    NULL,         // no window title //    WS_CHILD | WS_VISIBLE | WS_VSCROLL |//    ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL| WS_BORDER,//    150, 150, 200, 200,   // set size in WM_SIZE message //    hwnd,         // parent window //    (HMENU)ID_EDITCHILD,   // edit control ID //    (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),//    NULL);        // pointer not needed //// Add text to the window. //SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)lpszLatin);return 0;case WM_COMMAND:if (wParam == BTN_BTN_1){TCHAR lpszLatinl[500]{};Edit_GetText(hwndEdit, lpszLatinl, 500);MessageBox(0, lpszLatinl ,L"提示", MB_OK);}else if (wParam == BTN_CHECHEBOX_1){MessageBox(0, L"CHECKBOX 被按下", L"提示", MB_OK);}else if (wParam == BTN_RADIO_1){MessageBox(0, L"RADIO 被按下", L"提示", MB_OK);}break;case WM_NOTIFY:switch (((LPNMHDR)lParam)->code){case NM_RCLICK:MessageBox(0, L"WC_TREEVIEW 被右键", L"提示", MB_OK);break;case NM_DBLCLK:HTREEITEM ht = TreeView_GetSelection(hwndTV);WCHAR namebuf[MAX_PATH]{};TVITEM tItem;tItem.mask = TVIF_TEXT;tItem.pszText = namebuf;tItem.cchTextMax = MAX_PATH;HTREEITEM htup = ht;std::wstring fpath;while (true){htup = TreeView_GetParent(hwndTV, htup);if (htup == NULL){break;}tItem.hItem = htup;TreeView_GetItem(hwndTV, &tItem);fpath = L"\\" + fpath;fpath = tItem.pszText + fpath + L"\\";}tItem.hItem = ht;TreeView_GetItem(hwndTV,&tItem );std::wstring path = tItem.pszText;std::vector<std::wstring>flist = GetFileList(fpath + path);for (auto& var : flist){InsrtTree(ht, 0, var);}//MessageBox(0,tItem.pszText , L"提示", MB_OK);break;}break;default:return DefWindowProc(hwnd, uMsg, wParam, lParam);}return 0;
}HTREEITEM AddItemToTree(HWND hwndTV, LPTSTR lpszItem, int nLevel)
{TVITEM tvi;TVINSERTSTRUCT tvins;static HTREEITEM hPrev = (HTREEITEM)TVI_FIRST;static HTREEITEM hPrevRootItem = NULL;static HTREEITEM hPrevLev2Item = NULL;HTREEITEM hti;tvi.mask = TVIF_TEXT | TVIF_IMAGE| TVIF_SELECTEDIMAGE | TVIF_PARAM;// Set the text of the item. tvi.pszText = lpszItem;tvi.cchTextMax = sizeof(tvi.pszText) / sizeof(tvi.pszText[0]);// Assume the item is not a parent item, so give it a // document image. //tvi.iImage = g_nDocument;//tvi.iSelectedImage = g_nDocument;// Save the heading level in the item's application-defined // data area. tvi.lParam = (LPARAM)nLevel;tvins.item = tvi;tvins.hInsertAfter = hPrev;// Set the parent item based on the specified level. if (nLevel == 1)tvins.hParent = TVI_ROOT;else if (nLevel == 2)tvins.hParent = hPrevRootItem;elsetvins.hParent = hPrevLev2Item;// Add the item to the tree-view control. hPrev = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM,0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);if (hPrev == NULL)return NULL;// Save the handle to the item. if (nLevel == 1)hPrevRootItem = hPrev;else if (nLevel == 2)hPrevLev2Item = hPrev;// The new item is a child item. Give the parent item a // closed folder bitmap to indicate it now has child items. if (nLevel > 1){hti = TreeView_GetParent(hwndTV, hPrev);tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;tvi.hItem = hti;//tvi.iImage = g_nClosed;//tvi.iSelectedImage = g_nClosed;TreeView_SetItem(hwndTV, &tvi);}return hPrev;
}//获取文件列表
std::vector<std::wstring> GetVolumeList()
{std::vector<std::wstring> voList;WCHAR DeviceName[MAX_PATH]{};HANDLE findHandle = FindFirstVolumeW(DeviceName, MAX_PATH);if (findHandle == INVALID_HANDLE_VALUE){return voList;}do{WCHAR pathName[MAX_PATH]{};DWORD len;GetVolumePathNamesForVolumeName(DeviceName, pathName, MAX_PATH, &len);if (len>1){voList.push_back(pathName);}} while (FindNextVolume(findHandle, DeviceName, MAX_PATH));FindVolumeClose(findHandle);return voList;
}/// <summary>
/// path 路径
/// </summary>
std::vector<std::wstring> GetFileList(std::wstring path)
{std::vector<std::wstring> voList;path += L"\\*";WIN32_FIND_DATAW ffd{};HANDLE fileHandle = FindFirstFile(path.c_str(),&ffd);if (INVALID_HANDLE_VALUE == fileHandle){return voList;}do{voList.push_back(ffd.cFileName);} while (FindNextFile(fileHandle,&ffd));FindClose(fileHandle);return voList;
}int WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR     lpCmdLine,int       nShowCmd)
{//std::vector<std::wstring> fList = GetFileList(L"c:\\");//for (auto& var : fList)//{//    MessageBox(NULL, var.c_str(), L"", MB_OK);//}WNDCLASSEX wndcls{};wndcls.cbSize = sizeof(WNDCLASSEX);wndcls.style = CS_SAVEBITS | CS_DROPSHADOW;wndcls.lpfnWndProc = MainWndProc;wndcls.hInstance = hInstance;wndcls.lpszClassName = L"chao";RegisterClassEx(&wndcls);HWND m_hwnd = CreateWindowEx(0,wndcls.lpszClassName,L"Chao",0,100, 100, 600, 800,NULL, NULL,hInstance,NULL);
/*HWND hwndButton = CreateWindow(L"BUTTON",  // Predefined class; Unicode assumed L"OK",      // Button text WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,  // Styles 10,         // x position 10,         // y position 100,        // Button width50,        // Button heightm_hwnd,     // Parent window(HMENU)BTN_BTN_1,       // No menu.(HINSTANCE)GetWindowLongPtr(m_hwnd, GWLP_HINSTANCE),NULL);      // Pointer not needed.HWND hwndCheckbox = CreateWindow(L"BUTTON",  // Predefined class; Unicode assumed L"CHECKBOX",      // Button text WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX,  // Styles 150,         // x position 10,         // y position 100,        // Button width50,        // Button heightm_hwnd,     // Parent window(HMENU)BTN_CHECHEBOX_1,       // No menu.(HINSTANCE)GetWindowLongPtr(m_hwnd, GWLP_HINSTANCE),NULL);      // Pointer not needed.HWND hwndRADIO = CreateWindow(L"BUTTON",  // Predefined class; Unicode assumed L"RADIO",      // Button text WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,  // Styles 10,         // x position 150,         // y position 100,        // Button width50,        // Button heightm_hwnd,     // Parent window(HMENU)BTN_RADIO_1,       // No menu.(HINSTANCE)GetWindowLongPtr(m_hwnd, GWLP_HINSTANCE),NULL);      // Pointer not needed.
*/InitCommonControls();HWND hwndTV = CreateWindowEx(0,WC_TREEVIEW,TEXT("Tree View"),WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_INFOTIP,10,10,300,500,m_hwnd,0,hInstance,NULL);std::vector<std::wstring> voList = GetVolumeList();for (auto& var : voList){AddItemToTree(hwndTV, (LPTSTR)var.c_str(), 1);/*MessageBox(NULL, var.c_str(), L"", MB_OK);*/}//AddItemToTree(hwndTV, (LPTSTR)L"ROOT", 1);//AddItemToTree(hwndTV, (LPTSTR)L"ROOT-2", 2);//AddItemToTree(hwndTV, (LPTSTR)L"ROOT-3", 3);//AddItemToTree(hwndTV, (LPTSTR)L"ROOT-2", 2);//AddItemToTree(hwndTV, (LPTSTR)L"ROOT", 1);//AddItemToTree(hwndTV, (LPTSTR)L"ROOT-2", 2);//AddItemToTree(hwndTV, (LPTSTR)L"ROOT-3", 3);//AddItemToTree(hwndTV, (LPTSTR)L"ROOT-2", 2);//AddItemToTree(hwndTV, (LPTSTR)L"ROOT-3", 3); //AddItemToTree(hwndTV, (LPTSTR)L"ROOT-3", 3);ShowWindow(m_hwnd,SW_NORMAL);BOOL bRet;MSG msg;while (GetMessage(&msg, m_hwnd, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}}

学习参考:

使用Windows API将文件显示到树形目录下 【C++ Windows API】_哔哩哔哩_bilibili

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/890099.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

个人开发者神器:5款高效的项目管理工具推荐

作为个人开发者,高效的项目管理是确保工作顺利进行的关键。在众多的项目管理工具中,轻量级的 APP 因其便捷性和实用性备受青睐。本文将为您推荐 5 款个人开发者的神器——轻量级项目管理 APP,帮助您提升工作效率,更好地实现项目目标。 禅道项目管理软件 禅道是一款专业且开…

drawio使用阿里云最新图标

简介 draw.io是一款免费的在线绘图工具,可用于创建各种类型的图表、流程图、组织结构图、网络拓扑图等。它具有易于使用的直观界面和丰富的图形库,支持与Google Drive、OneDrive、Dropbox等云存储服务集成。用户可以直接在浏览器中使用draw.io,也可以将其安装为Chrome应用程…

VulnHub-DC-6靶机-wpscan爆破+命令注入反弹shell+nmap提权

一、环境搭建 选择扫描虚拟机选择靶机路径这里如果出现报错,无法导入,如VMware出现配置文件 .vmx 是由VMware产品创建,但该产品与此版 VMware workstation 不兼容,因此无法使用(VMware版本不兼容问题),可以修改.vmx文件版本和虚拟机一致二、信息收集 扫描ip nmap -sn 19…

浅析Golang的内存管理(中篇): go runtime的内存管理模型与内存分配器

文章目录go runtime的基本内存模型 三级存储体系(MCache,MCentral,Mheap) 对象分配流程 一、go runtime的基本内存模型go runtime 借鉴了C++的内存模型和TCMalloc(Thread-Caching Malloc)内存分配机制,再开始之前,先了解一些go runtime对内存对象抽象的名词概念,它们分…

浅析Golang的内存管理(上篇):操作系统内存管理

文章目录计算机存储体系介绍 虚拟存储器 内存管理单元与页式存储管理 CPU发起一次访存的全过程 一、计算机存储体系介绍从计算机的组成角度来看,计算机的存储分为,寄存器-高速缓存-主存储器(泛指内存)-本地存储(磁盘)-外部存储(光盘、云盘等),由下到上,运行速度越来…

SVN介绍与安装

一、svn介绍 1、svn是一个版本控制工具; -svN是subversion的简称:是一个开放源代码的版本控制系统,通过采用分支管理系统的高效管理,简而言之就是用于多个人共同开发同一个项目,实现共享资源,实现最终集中式的管理。 -SVN的作用:在项目组当中对需求规格说明书、测试用例、…

提示词装饰器:一种改善AI生成回复的简单方式

通过结构化提示解锁AI的全部潜力 人工智能是一种非常强大的工具,但其回应的质量往往取决于我们与其沟通的有效性。如果你曾经在从AI模型获得精确且结构良好的回答时遇到困难,你并不孤单。许多用户在提示制定中面临不一致、模糊的回应或过多的试验和错误。那么,是否有一种方法…

信息安全项目管理工具:等保2.0要求的3类检测系统

随着信息技术的飞速发展,信息安全问题日益凸显。等保 2.0 作为我国网络安全领域的重要标准,对信息安全提出了更高的要求。在等保 2.0 的要求下,信息安全项目管理工具中的 3 类检测系统发挥着至关重要的作用。本文将详细介绍这 3 类检测系统,帮助读者更好地了解信息安全领域…

[c++算法] 树的直径,包教包会!

哈喽大家好,我是 doooge。今天我们要将数论中的一个算法-树的直径。 $$\Huge 树的直径 详解$$ 1.树的直径是什么 这是一棵图论中的树:这棵树的直径就是这棵树中最长的一条简单路径。 2.树的直径怎么求 2.1暴力算法 直接对每个点进行 DFS,找到每个点离最远的点的距离,最后求…

图吧工具箱PC电脑工具(图拉丁吧硬件检测工具箱) v2025.01 中文绿色便携版

点击上方蓝字关注我 前言 图吧工具箱(大家通常叫它图拉丁吧硬件检测工具箱)是一个完全免费、开源、没有广告的硬件检测工具集合。这个工具箱是专门为喜欢自己动手组装电脑(DIY)的朋友们,特别是图钉社区的成员们制作的。里面包含了好多常用的硬件测试和检测小工具,特别适合…

在Windows上安装UOS打印机

因自己放在办公室发挥余热的Windows电脑即将寿终正寝,所以这两天试着将包括文件打印在内的基础网络服务逐渐转移到UOS主机上。 参照官方教程一通操作,Windows始终在添加打印机页面找不到同个局域网下的UOS主机,点击疑难解答则提示“该设备或资源未设置为接受端口“文件和打印…

是不是长大之后便很难再专注了?

写在前面 1100 字 | 专注 | 思考 | 逆向思维 正文“上课要专心。”我们似乎总能听见大人们这样要求我们。不过坦白地说,我真正体验过全神贯注的时刻,就那么一两次。看起来这篇文章,似乎又要大吐苦水,谈论生活怎样艰辛困苦,各种科技产品怎样将人碎片化之类。并不是。 恰恰相…