• 数据格式
  • 内存配置
  • 将文字传送到剪贴簿
  • 从剪贴簿上取得文字
  • 剪贴板的简单使用
  • 延迟提出
  • 自定义数据格式
  • 剪贴板浏览器

Windows剪贴板允许把数据从一个程序传送到另一个程序中。它的原理相对而言比较简单,把数据存放到剪贴板上的程序或从剪贴板上取出数据的程序都无须太多的负担。

数据格式

CF_TEXT以NULL结尾的ANSI字符集字符串。它在每行末尾包含一个carriage return和linefeed字符。
CF_OEMTEXT含有文字数据(与CF_TEXT类似)的内存块。但是它使用的是OEM字符集。
CF_LOCALE一个国家地区标识符的句柄。表示剪贴簿文字使用的国别地区设定。
CF_BITMAP与设备相关的位图格式。
CF_DIB定义一个设备无关位图的内存块。
CF_PALETTE调色盘句柄。它通常与CF_DIB配合使用,以定义与设备相关的位图所使用的颜色调色盘。
CF_TIFF含有标号图像文件格式(TIFF)数据的整体内存块。
CF_METAFILEPICT以旧的metafile格式存放的图片。
CF_ENHMETAFILE增强型metafile(32位Windows支持的)句柄
CF_PENDATA与Windows的笔式输入扩充功能联合使用。
CF_WAVE声音(波形)文件。
CF_RIFF使用资源交换文件格式(Resource Interchange File Format)的多媒体数据。
CF_HDROP与拖放服务相关的文件列表。

内存配置

程序向剪贴簿传输一些数据的时候,必须配置一个内存块,并且将这块内存交给剪贴簿处理。早期的程序中需要配置内存时,我们只需使用标准C执行时期链接库所支持的malloc函数。但是,由于在Windows中执行的应用程序之间必须要共享剪贴簿所储存的内存块,这时malloc函数就有些不适任这项任务了。

要用Windows API来配置一个内存块,可以调用:

hGlobal = GlobalAlloc (uiFlags, dwSize) ;

此函数有两个参数:一系列可能的旗标和内存块的字节大小。函数传回一个HGLOBAL型态的句柄,称为整体内存块句柄整体句柄。传回值为NULL表示不能配置足够的内存。

虽然GlobalAlloc的两个参数略有不同,但它们都是32位的无正负号整数。如果将第一个参数设定为0,那么您就可以更有效地使用旗标GMEM_FIXED。在这种情况下,GlobalAlloc传回的整体句柄实际是指向所配置内存块的指针。如 果 不 喜 欢 将 内 存 块 中 的 每 一 位 都 初 始 化 为 0 , 那 么 您 也 能 够 使 用 旗 标GMEM_ZEROINIT。在Windows表头文件中,简洁的GPTR旗标定义为GMEM_FIXED和GMEM_ZEROINIT旗标的组合:

#define GPTR (GMEM_FIXED | GMEM_ZEROINIT)

下面是一个重新配置函数:

hGlobal = GlobalReAlloc (hGlobal, dwSize, uiFlags) ;

如果内存块扩大了,您可以用GMEM_ZEROINIT旗标将新的字节设为0。
下面是获得内存块大小的函数:

dwSize = GlobalSize (hGlobal) ;

释放内存块的函数:

GlobalFree (hGlobal) ;

简写标识符:

#define GHND (GMEM_MOVEABLE | GMEM_ZEROINIT)

GMEM_MOVEABLE旗标允许Windows在虚拟内存中移动一个内存块。这不是说将在物理内存中移动内存块,只是应用程序用于读写这块内存的地址可以被变动。尽管GMEM_MOVEABLE是16位Windows的通则,但是它的作用现在已经少得多了。如果您的应用程序频繁地配置、重新配置以及释放不同大小的内存块,应用程序的虚拟地址空间将会变得支离破碎。可以想象得到,最后虚拟内存地址空间就会被用完。如果这是个可能会发生的问题,那么您将希望内存是可移动的。下面就介绍如何让内存块成为可搬移位置的。
首先定义一个指标(例如,一个int型态的)和一个GLOBALHANDLE型态的变量:

int * p ;
GLOBALHANDLE hGlobal ;

然后配置内存。例如:

hGlobal = GlobalAlloc (GHND, 1024) ;

与处理其它Windows句柄一样,您不必担心数字的实际意义,只要照著作就好了。需要存取内存块时,可以呼叫:

p = (int *) GlobalLock (hGlobal) ;

此函数将句柄转换为指标。在内存块被锁定期间,Windows将固定虚拟内存中的地址,不再移动那块内存。存取结束后呼叫:

GlobalUnlock (hGlobal) ;

这将使Windows可以在虚拟内存中移动内存块。要真正确保此程序正常运作(体验早期Windows程序写作者的痛苦经历),您应该在单一个消息处理期间锁定和解锁内存块。
在释放内存时,呼叫GlobalFree应使用句柄而不是指标。如果您现在不能存取句柄,可以使用下面的函数:

hGlobal = GlobalHandle (p) ;

在解锁之前,您能够多次锁定一个内存块。Windows保留一个锁定次数,而且在内存块可被自由移动之前,每次锁定都需要相对应的解锁。当Windows在虚拟内存中移动一个内存块时,不需要将字节从一个位置复制到另一个,只需巧妙地处理内存页映像表。通常,让32位Windows为您的程序配置可移动的内存块,其唯一确实的理由只是避免虚拟内存的空间碎裂出现。使用剪贴簿时,也应该使用可移动内存。
为剪贴簿配置内存时,您应该以GMEM_MOVEABLE和GMEM_SHARE旗标呼叫GlobalAlloc函数。GMEM_SHARE旗标使得其它应用程序也可以使用那块内存。

将文字传送到剪贴簿

让我们想象把一个ANSI字符串传送到剪贴簿上,并且我们已经有了指向这个字符串的指针(pString)。现在希望传送这个字符串的iLength字符,这些字符可能以NULL结尾,也可能
不以NULL结尾。
首先,通过使用GlobalAlloc来配置一个足以储存字符串的内存块,其中还包括一个终止字符NULL:

hGlobal = GlobalAlloc (GHND | GMEM_SHARE, iLength + 1) ;

如果未能配置到内存块,hGlobal的值将为NULL 。如果配置成功,则锁定这块内存,并得到指向它的一个指标:

pGlobal = GlobalLock (hGlobal) ;

将字符串复制到内存块中:

for (i = 0 ; i < wLength ; i++)
*pGlobal++ = *pString++ ;

由于GlobalAlloc的GHND旗标已使整个内存块在配置期间被清除为零,所以不需要增加结尾的NULL 。以下叙述为内存块解锁:

GlobalUnlock (hGlobal) ;

现在就有了表示以NULL结尾的文字所在内存块的内存句柄。为了把它送到剪贴簿中,打开剪贴簿并把它清空:

OpenClipboard (hwnd) ;
EmptyClipboard () ;

利用CF_TEXT标识符把内存句柄交给剪贴簿,关闭剪贴簿:

SetClipboardData (CF_TEXT, hGlobal) ;
CloseClipboard () ;

工作告一段落。
下面是关于此过程的一些规则:

在处理同一个消息的过程中呼叫OpenClipboard和CloseClipboard。不需要时,不要打开剪贴簿。
不要把锁定的内存句柄交给剪贴簿。
当呼叫SetClipboardData后,请不要再继续使用该内存块。它不再属于使用者程序,必须把句柄看成是无效的。如果需要继续存取数据,可以制作数据的副本,或从剪贴簿中读取它(如下节所述)。您也可以在SetClipboardData呼叫和CloseClipboard呼叫之间继续使用内存块,但是不要使用传递给SetClipboardData函数的整体句柄。事实上,此函数也传回一个整体句柄,必需锁定这些代码以存取内存。在呼叫CloseClipboard之前,应先为此句柄解锁。

从剪贴簿上取得文字

从剪贴簿上取得文字只比把文字传送到剪贴簿上稍微复杂一些。您必须首先确定剪贴簿是否含有CF_TEXT格式的数据,最简单的方法是呼叫

bAvailable = IsClipboardFormatAvailable (CF_TEXT) ;

如果剪贴簿上含有CF_TEXT数据,这个函数将传回TRUE(非零)。
IsClipboardFormatAvailable是少数几个不需先打开剪贴簿就可以使用的剪贴簿函数之一。但是,如果您之后想再打开剪贴簿以取得这个文字,就应该再做一次检查(使用同样的函数或其它方法),以便确定CF_TEXT数据是否仍然留在剪贴簿中。

为了传送出文字,首先打开剪贴簿:

OpenClipboard (hwnd) ;

会得到代表文字的内存块代号:

hGlobal = GetClipboardData (CF_TEXT) ;

如果剪贴簿不包含CF_TEXT格式的数据,此句柄就为NULL。这是确定剪贴簿是否含有文字的另一种方法。如果GetClipboardData传回NULL,则关闭剪贴簿,不做其它任何工作。
从 GetClipboardData 得 到 的 句 柄 并 不 属 于 使 用 者 程 序 - 它 属 于 剪 贴 簿 。 仅 在GetClipboardData和CloseClipboard呼叫之间这个句柄才有效。您不能释放这个句柄或
更改它所引用的数据。如果需要继续存取这些数据,必须制作这个内存块的副本。
这里有一种将数据复制到使用者程序中的方法。首先,配置一块与剪贴簿数据块大小相同的内存块,并配置一个指向该块的指标:

pText = (char *) malloc (GlobalSize (hGlobal)) ;

再次呼叫hGlobal ,而hGlobal是从GetClipboardData呼叫传回的整体句柄。现在锁定句柄,获得一个指向剪贴簿块的指针:

pGlobal = GlobalLock (hGlobal) ;

现在就可以复制数据了:

strcpy (pText, pGlobal) ;

或者,您可以使用一些简单的C程序代码:

while (*pText++ = *pGlobal++) ;

在关闭剪贴簿之前先解锁内存块:

GlobalUnlock (hGlobal) ;
CloseClipboard () ;

剪贴板的简单使用

ClipText.rc

/
//
// Menu
//CLIPTEXT MENU DISCARDABLE
BEGINPOPUP "&Edit"BEGINMENUITEM "Cu&t\tCtrl+X",                IDM_EDIT_CUTMENUITEM "&Copy\tCtrl+C",               IDM_EDIT_COPYMENUITEM "&Paste\tCtrl+V",              IDM_EDIT_PASTEMENUITEM "De&lete\tDel",                IDM_EDIT_CLEARMENUITEM SEPARATORMENUITEM "&Reset",                      IDM_EDIT_RESETEND
END/
//
// Accelerator
//CLIPTEXT ACCELERATORS DISCARDABLE
BEGIN"C",            IDM_EDIT_COPY,          VIRTKEY, CONTROL, NOINVERT"V",            IDM_EDIT_PASTE,         VIRTKEY, CONTROL, NOINVERTVK_DELETE,      IDM_EDIT_CLEAR,         VIRTKEY, NOINVERT"X",            IDM_EDIT_CUT,           VIRTKEY, CONTROL, NOINVERT
END

RESOURCE.H

#define IDM_EDIT_CUT                    40001
#define IDM_EDIT_COPY                   40002
#define IDM_EDIT_PASTE                  40003
#define IDM_EDIT_CLEAR                  40004
#define IDM_EDIT_RESET                  40005

ClipText.c

/*-----------------------------------------CLIPTEXT.C -- The Clipboard and Text(c) Charles Petzold, 1998-----------------------------------------*/#include <windows.h>
#include "resource.h"LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;// 根据是否是Unicode来设置默认内容和标题
#ifdef UNICODE#define CF_TCHAR CF_UNICODETEXT
TCHAR szDefaultText[] = TEXT ("Default Text - Unicode Version") ;
TCHAR szCaption[]     = TEXT ("Clipboard Text Transfers - Unicode Version") ;#else#define CF_TCHAR CF_TEXT
TCHAR szDefaultText[] = TEXT ("Default Text - ANSI Version") ;
TCHAR szCaption[]     = TEXT ("Clipboard Text Transfers - ANSI Version") ;#endifint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{static TCHAR szAppName[] = TEXT ("ClipText") ;HACCEL       hAccel ;HWND         hwnd ;MSG          msg ;WNDCLASS     wndclass ;wndclass.style         = CS_HREDRAW | CS_VREDRAW ;wndclass.lpfnWndProc   = WndProc ;wndclass.cbClsExtra    = 0 ;wndclass.cbWndExtra    = 0 ;wndclass.hInstance     = hInstance ;wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;wndclass.lpszMenuName  = szAppName ;wndclass.lpszClassName = szAppName ;if (!RegisterClass (&wndclass)){MessageBox (NULL, TEXT ("This program requires Windows NT!"),szAppName, MB_ICONERROR) ;return 0 ;}hwnd = CreateWindow (szAppName, szCaption,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance, NULL) ;ShowWindow (hwnd, iCmdShow) ;UpdateWindow (hwnd) ;hAccel = LoadAccelerators (hInstance, szAppName) ;while (GetMessage (&msg, NULL, 0, 0)){if (!TranslateAccelerator (hwnd, hAccel, &msg)){TranslateMessage (&msg) ;DispatchMessage (&msg) ;}}return msg.wParam ;
}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{static PTSTR pText ;BOOL         bEnable ;HGLOBAL      hGlobal ;HDC          hdc ;PTSTR        pGlobal ;PAINTSTRUCT  ps ;RECT         rect ;switch (message){case WM_CREATE:SendMessage (hwnd, WM_COMMAND, IDM_EDIT_RESET, 0) ;return 0 ;case WM_INITMENUPOPUP:// IsClipboardFormatAvailable判断是否含有CF_TEXT格式的数据EnableMenuItem ((HMENU) wParam, IDM_EDIT_PASTE,IsClipboardFormatAvailable (CF_TCHAR) ? MF_ENABLED : MF_GRAYED) ;bEnable = pText ? MF_ENABLED : MF_GRAYED ;EnableMenuItem ((HMENU) wParam, IDM_EDIT_CUT,   bEnable) ;EnableMenuItem ((HMENU) wParam, IDM_EDIT_COPY,  bEnable) ;EnableMenuItem ((HMENU) wParam, IDM_EDIT_CLEAR, bEnable) ;break ;case WM_COMMAND:switch (LOWORD (wParam)){case IDM_EDIT_PASTE:// 打开剪贴板OpenClipboard (hwnd) ;// 获取剪贴板整体句柄if (hGlobal = GetClipboardData (CF_TCHAR)){// 锁定整体句柄,获取指向剪贴板指针pGlobal = GlobalLock (hGlobal) ;if (pText){free (pText) ;pText = NULL ;}// 根据整体句柄里剪贴板大小分配内存pText = malloc (GlobalSize (hGlobal)) ;// 拷贝一份lstrcpy (pText, pGlobal) ;InvalidateRect (hwnd, NULL, TRUE) ;}CloseClipboard () ;return 0 ;case IDM_EDIT_CUT:case IDM_EDIT_COPY:if (!pText)return 0 ;// 分配整体句柄足够大小的内存hGlobal = GlobalAlloc (GHND | GMEM_SHARE, (lstrlen (pText) + 1) * sizeof (TCHAR)) ;// 锁定整体句柄,然后返回剪贴板指针pGlobal = GlobalLock (hGlobal) ;// 拷贝lstrcpy (pGlobal, pText) ;// 再次锁定GlobalUnlock (hGlobal) ;// 打开剪贴板OpenClipboard (hwnd) ;// 清空剪贴板EmptyClipboard () ;// 把整体句柄交还给剪贴板SetClipboardData (CF_TCHAR, hGlobal) ;// 关闭剪贴板CloseClipboard () ;if (LOWORD (wParam) == IDM_EDIT_COPY)return 0 ;        // fall through for IDM_EDIT_CUTcase IDM_EDIT_CLEAR:if (pText){free (pText) ;pText = NULL ;}InvalidateRect (hwnd, NULL, TRUE) ;return 0 ;case IDM_EDIT_RESET:if (pText){free (pText) ;pText = NULL ;}pText = malloc ((lstrlen (szDefaultText) + 1) * sizeof (TCHAR)) ;lstrcpy (pText, szDefaultText) ;InvalidateRect (hwnd, NULL, TRUE) ;return 0 ;}break ;case WM_PAINT:hdc = BeginPaint (hwnd, &ps) ;GetClientRect (hwnd, &rect) ;if (pText != NULL)DrawText (hdc, pText, -1, &rect, DT_EXPANDTABS | DT_WORDBREAK) ;EndPaint (hwnd, &ps) ;return 0 ;case WM_DESTROY:if (pText)free (pText) ;PostQuitMessage (0) ;return 0 ;}return DefWindowProc (hwnd, message, wParam, lParam) ;
}

可以看到,在将数据准备好之后,从剪贴板传输数据时需要四个调用:

复制

OpenClipboard (hwnd) ;
EmptyClipboard () ;
SetClipboardData (iFormat, hGlobal) ;
CloseClipboard () ;

存取这些数据需要三个调用:

粘贴

OpenClipboard (hwnd) ;
hGlobal = GetClipboardData (iFormat) ;
// 其它行程序
CloseClipboard () ;

延迟提出

当把数据放入剪贴簿中时,一般来说要制作一份数据的副本,并将包含这份副本的内存块句柄传给剪贴簿。对非常大的数据项来说,这种方法会浪费内存空间。如果使用者不想把数据粘贴到另一个程序里,那么,在被其它内容取代之前,它将一直占据着内存空间。通过使用一种叫做「延迟提出」的技术可以避免这个问题。实际上,直到另一个程序需要数据,程序才提供这份数据。为此,不将数据句柄传给Windows,而是在SetClipboardData呼叫中使用NULL:

OpenClipboard (hwnd) ;
EmptyClipboard () ;
SetClipboardData (iFormat, NULL) ;
CloseClipboard () ;

自定义数据格式

共三种方法:

  • 在SetClipboardData和GetClipboardData呼叫中可使用下列wFormat值:CF_DSPTEXT、CF_DSPBITMAP、CF_DSPMETAFILEPICT或CF_DSPENHMETAFILE(字母DSP代表「显示器」);
  • CF_OWNERDISPLAY旗标
  • 注册自己的剪贴簿格式名

剪贴板浏览器

/*-----------------------------------------CLIPVIEW.C -- Simple Clipboard Viewer(c) Charles Petzold, 1998-----------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{static TCHAR szAppName[] = TEXT ("ClipView") ;HWND         hwnd ;MSG          msg ;WNDCLASS     wndclass ;wndclass.style         = CS_HREDRAW | CS_VREDRAW ;wndclass.lpfnWndProc   = WndProc ;wndclass.cbClsExtra    = 0 ;wndclass.cbWndExtra    = 0 ;wndclass.hInstance     = hInstance ;wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;wndclass.lpszMenuName  = NULL ;wndclass.lpszClassName = szAppName ;if (!RegisterClass (&wndclass)){MessageBox (NULL, TEXT ("This program requires Windows NT!"),szAppName, MB_ICONERROR) ;return 0 ;}hwnd = CreateWindow (szAppName, TEXT ("Simple Clipboard Viewer (Text Only)"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance, NULL) ;ShowWindow (hwnd, iCmdShow) ;UpdateWindow (hwnd) ;while (GetMessage (&msg, NULL, 0, 0)){TranslateMessage (&msg) ;DispatchMessage (&msg) ;}return msg.wParam ;
}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{static HWND hwndNextViewer ;HGLOBAL     hGlobal ;HDC         hdc ;PTSTR       pGlobal ;PAINTSTRUCT ps ;RECT        rect ;switch (message){case WM_CREATE:// 成为剪贴板浏览器链的一部分// 最后一个剪贴板浏览器返回hwndNextViewer为NullhwndNextViewer = SetClipboardViewer (hwnd) ;return 0 ;case WM_CHANGECBCHAIN:if ((HWND) wParam == hwndNextViewer)hwndNextViewer = (HWND) lParam ;else if (hwndNextViewer)SendMessage (hwndNextViewer, message, wParam, lParam) ;return 0 ;// windows发送给目前剪贴板浏览器// 区别:WM_PAINTCLIPBOARD是由剪贴簿浏览器发送给使用CF_OWNERDISPLAY// 剪贴板数据格式的程序case WM_DRAWCLIPBOARD:if (hwndNextViewer)// 发送给下一个剪贴板浏览器SendMessage (hwndNextViewer, message, wParam, lParam) ;InvalidateRect (hwnd, NULL, TRUE) ;return 0 ;case WM_PAINT:hdc = BeginPaint (hwnd, &ps) ;GetClientRect (hwnd, &rect) ;// 打开剪贴板OpenClipboard (hwnd) ;#ifdef UNICODE// 获取全局内存句柄hGlobal = GetClipboardData (CF_UNICODETEXT) ;
#elsehGlobal = GetClipboardData (CF_TEXT) ;
#endifif (hGlobal != NULL){pGlobal = (PTSTR) GlobalLock (hGlobal) ;DrawText (hdc, pGlobal, -1, &rect, DT_EXPANDTABS) ;GlobalUnlock (hGlobal) ;}// 关闭剪贴板CloseClipboard () ;EndPaint (hwnd, &ps) ;return 0 ;case WM_DESTROY:// 从剪贴板链中删除自己,windows会发送WM_CHANGECBCHAINChangeClipboardChain (hwnd, hwndNextViewer) ;PostQuitMessage (0) ;return 0 ;}return DefWindowProc (hwnd, message, wParam, lParam) ;
}

处理标准格式(如Windows提供的那个剪贴簿一样)以外的数据格式的剪贴簿浏览器还需要完成一些其它工作,比如显示剪贴簿中目前所有数据格式的名称。使用者可以通过呼叫
EnumClipboardFormats并使用GetClipboardFormatName得到非标准数据格式名称来完成这项工作。使用CF_OWNERDISPLAY数据格式的剪贴簿浏览器必须把下面四个消
息送往剪贴簿数据的拥有者以显示该资料:

WM_PAINTCLIPBOARD
WM_SIZECLIPBOARD
WM_VSCROLLCLIPBOARD
WM_HSCROLLCLIPBOARD

如果您想编写这样的剪贴簿浏览器,那么必须使用GetClipboardOwner获得剪贴簿所有者的窗口句柄,并当您需要修改剪贴簿的显示区域时,将这些消息发送给该窗口。

Windows程序设计-剪贴板相关推荐

  1. 中年人学C语言Windows程序设计,28 EDIT文本编辑框控件

    创建编辑框控件 编辑框控件的窗口类名是edit.除了子窗口常用的风格 WS_CHILD. WS_VISIBLE.WS_BORDER 外,edit 控件也有自己的风格,都是以ES开头. 风格 说明 ES ...

  2. Windows程序设计学习笔记(1):一个简单的windows程序

    <Windows程序设计>(第五版)(美Charles Petzold著) 1 #include<windows.h> 2 3 LRESULT CALLBACK WndProc ...

  3. Windows程序设计------字体不等宽引出的问题及其细节知识

    在写Windows程序设计的Typer程序时,我并不是在每一个使用HDC的地方都重新创建选中字体,而是在一开始选中之后,就没有再删除它,代码如图: 结果我的字体不是等宽字体! 起先我以为是没有设置WM ...

  4. Windows程序设计“圣经”

    Windows程序设计"圣经" 十年依旧畅销不衰的神品 传奇大师带你走入Windows编程圣殿 "Windows程序设计最举足轻重的书当然就是Charles Petzol ...

  5. 侯捷:搞Windows程序设计我们需要啥

    侯捷:搞Windows程序设计我们需要啥 如果你是一位资深的Windows程序员,相信你对Jeffrey Richter一定不会陌生,是不是有些崇拜和景仰?如果你是一位刚涉足这个领域的Windows程 ...

  6. Windows程序设计之创建窗口示例

    Windows程序设计书本上的创建窗口示例,手敲代码,拿出了show,记录一下而已~~~ 一.代码如下: #include <tchar.h> #include <windows.h ...

  7. c语言lnk1168无法打开exe,跪求大佬帮帮看看LINK : fatal error LNK1168: 无法打开 F:\windows程序设计\窗口\......

    马上注册,结交更多好友,享用更多功能^_^ 您需要 登录 才可以下载或查看,没有帐号?立即注册 x 运行的结果显示是这样: 1>------ 已启动生成: 项目: 窗口, 配置: Debug W ...

  8. createprocess重启程序_C++_VC程序设计中CreateProcess用法注意事项,对于windows程序设计来说,启动 - phpStudy...

    VC程序设计中CreateProcess用法注意事项 对于windows程序设计来说,启动一个进程有三种方法:WinExec,ShellExecute,CreateProcess.这里仅对Create ...

  9. windows程序设计.第一个windos程序

    Windows程序设计(第5版) windows程序需要调用API. 第一个Windows程序 1 /*HelloMsg.c -- Displays "Hello World!" ...

最新文章

  1. linux unset命令,Linux unset命令
  2. WP7 开发(十) 处理Html标记
  3. UNIX环境高级编程第三章
  4. 新概念一册电子书课本_新概念英语第二册完整版:音频+动画视频+课本图文讲解...
  5. ftp搭建后为什么登录不了??_为什么防爆胎就是普及不了?知道真相后,你也许会心凉一大截...
  6. ubuntu 安装docker报错
  7. [vue] vue中怎么重置data?
  8. Jquery Uploadify插件+Servlet解决FTP多文件上传
  9. Swift - 键盘弹出样式
  10. 纯 css 实现 a 标签 loading 效果
  11. static 静态局部变量
  12. 使用自定义功能构建Mamdani系统
  13. linux命令应用大词典.pdf,Linux命令应用大词典
  14. 深度强化学习之近端策略优化(Proximal Policy Optimization)
  15. html链接抓取,【SEO工具】网页超链接提取工具(无语网站链接抓取器)
  16. 工作站性能测试软件,国产工作站“王炸”来了! 曙光桌面工作站评测
  17. linux图片处理软件,Ubuntu 下图像处理软件汇总
  18. 调用百度地图API实现连线高铁线路的调用示例
  19. 基于数据形式说明杜兰特的技术特点的分析(含Python实现讲解部分)
  20. __attribute__((__aligned__(n)))对结构体对齐的影响

热门文章

  1. Springboot 整合 Current-Limiting 实现接口限流
  2. 计算RSBF各项指标
  3. kesu移动硬盘(固态硬盘)插上电脑后不显示盘符的解决办法
  4. 如何提问,才能让别人回答我们的问题呢?
  5. 字符串:1.给定一个字符串s,分割s使得s的每一个子串都是回文串
  6. JDK各个版本安装以及配置,超详细
  7. android 高性能框架,高性能架构
  8. 58同城自动登录功能 分享给大家!
  9. GUID 分区表详解
  10. 如何通过微信与手机连接到服务器,本地服务器和微信服务器的具体通信过程是怎样的...