⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 见招拆招《windows程序设计》(十一) .txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 4 页
字号:
                                 SendMessage (hwndNextViewer, message, wParam, lParam) ;
        
           return 0 ;
        
不一定要使用else if叙述,它只用于保证hwndNextViewer为非NULL的值。hwndNextViewer的值为NULL时,执行这段程序代码的程序就是链中最后一个浏览器,而这是不可能的。

当程序快结束时,如果它仍然在剪切板浏览器链中,则必须从链中删除它。您可以在处理WM_DESTROY消息时呼叫ChangeClipboardChain来完成这项工作。

case        WM_DESTROY :
        
    ChangeClipboardChain (hwnd, hwndNextViewer) ;
        
           PostQuitMessage (0) ;
        
           return 0 ;
        
Windows还有一个允许程序获得第一个剪切板浏览器窗口句柄的函数:

hwndViewer = GetClipboardViewer () ;
        
一般来说不需要这个函数。如果没有目前的剪切板浏览器,则传回值为NULL。

下面是一个说明剪切板浏览器链如何工作的例子。当Windows刚启动时,目前剪切板浏览器是NULL:

剪切板浏览器:NULL

一个具有hwnd1窗口句柄的程序呼叫SetClipboardViewer。这个函数传回的NULL成为这个程序中的hwndNextViewer值:

目前剪切板浏览器:hwnd1

hwnd1的下一个浏览器:NULL

第二个具有hwnd2窗口句柄的程序呼叫SetClipboardViewer ,并传回hwnd1:

目前的剪切板浏览器:hwnd2

hwnd2的下一个浏览器:hwnd1

hwnd1的下一个浏览器:NULL

每三个程序(hwnd3)和第四个程序(hwnd4) 也呼叫SetClipboardViewer ,并且传回hwnd2和hwnd3:

目前的剪切板浏览器:hwnd4

hwnd4的下一个浏览器:hwnd3

hwnd3的下一个浏览器:hwnd2

hwnd2的下一个浏览器:hwnd1

hwnd1的下一个浏览器:NULL

当剪切板的内容发生变化时,Windows发送一个WM_DRAWCLIPBOARD消息给hwnd4,hwnd4发送消息给hwnd3,hwnd3发送消息给hwnd2,hwnd2发送消息给hwnd1,hwnd1传回。

现在hwnd2决定通过下列呼叫从链中删除自己:

ChangeClipboardChain (hwnd2, hwnd1) ;

Windows将wParam等于hwnd2、lParam等于hwnd1的WM_CHANGECBCHAIN消息发送给hwnd4。由于hwnd4的下一个测览器是hwnd3,所以hwnd4把这个消息传给hwnd3。现在hwnd3注意到wParam等于它的下一个测览器(hwnd2),所以将下一个浏览器设定为lParam (hwnd1)并且传回。这样工作就完成了。现在剪切板浏览器链如下:

目前剪切板浏览器:hwnd4

hwnd4的下一个浏览器:hwnd3

hwnd3的下一个浏览器:hwnd1

hwnd1的下一个浏览器:NULL

一个简单的剪切板浏览器


剪切板浏览器不一定要像Windows所提供的那样完善,例如,剪切板浏览器可以只显示一种剪切板数据格式。程序12-2中所示的CLIPVIEW程序是一种只能显示CF_TEXT格式的剪切板浏览器。

程序12-2  CLIPVIEW
        
CLIPVIEW.ASM

;MASMPlus 代码模板 - 普通的 Windows 程序代码

.386
.Model Flat, StdCall
Option Casemap :None

Include windows.inc
Include user32.inc
Include kernel32.inc
Include gdi32.inc

includelib gdi32.lib
IncludeLib user32.lib
IncludeLib kernel32.lib
include macro.asm
	
	WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD

.DATA
	szAppName	TCHAR	"ClipView",0
.DATA?
	hInstance	HINSTANCE	?
        hwndNextViewer  HWND		?

.CODE
START:
	invoke GetModuleHandle,NULL
	invoke WinMain,eax,NULL,NULL,SW_SHOWDEFAULT
	invoke ExitProcess,0
WinMain proc hInst:DWORD,hPrevInst:DWORD,szCmdLine:DWORD,iCmdShow:DWORD
	LOCAL wndclass   :WNDCLASSEX
	LOCAL msg  :MSG
	LOCAL hWnd :HWND
	LOCAL hAccel:HACCEL

	mov wndclass.cbSize,sizeof WNDCLASSEX	
	mov wndclass.style,CS_HREDRAW or CS_VREDRAW	
	mov wndclass.lpfnWndProc,offset WndProc

	mov wndclass.cbClsExtra,0
	mov wndclass.cbWndExtra,0
	
	push hInst
	pop wndclass.hInstance
	
	invoke LoadIcon,hInst,addr szAppName
	mov wndclass.hIcon,eax	
	
	invoke LoadCursor,NULL,IDC_ARROW
	mov wndclass.hCursor,eax	
	
	invoke GetStockObject,WHITE_BRUSH
	mov wndclass.hbrBackground,EAX
	
	lea eax,szAppName
	mov wndclass.lpszMenuName,eax
	mov wndclass.lpszClassName,eax

	mov wndclass.hIconSm,0
	
	invoke RegisterClassEx, ADDR wndclass
	.if (eax==0)
	   invoke MessageBox,NULL,CTXT("This program requires Windows NT!"),szAppName, MB_ICONERROR
           ret
	.endif
        
   
	invoke CreateWindowEx,NULL,
			ADDR szAppName, 					;window class name
			CTXT("Simple Clipboard Viewer (Text Only)"), 
			WS_OVERLAPPEDWINDOW,					;window style
			CW_USEDEFAULT,						;initial x position
			CW_USEDEFAULT,						;initial y position
			CW_USEDEFAULT, 						;initial x size
			CW_USEDEFAULT,						;initial y size
			NULL,							;parent window handle
			NULL,							;window menu handle
			hInst,							;program instance handle
			NULL										;creation parameters
	mov hWnd,eax


  	invoke ShowWindow,hWnd,iCmdShow
	invoke UpdateWindow,hWnd
	
	invoke	LoadAccelerators,hInstance,addr szAppName
	mov	hAccel,eax

	StartLoop:
		invoke GetMessage,ADDR msg,NULL,0,0
			cmp eax, 0
			je ExitLoop
				invoke TranslateMessage, ADDR msg
				invoke DispatchMessage,  ADDR msg
			jmp StartLoop
	ExitLoop:
	
	mov eax,msg.wParam
	ret
WinMain endp


WndProc proc hwnd:DWORD,uMsg:DWORD,wParam :DWORD,lParam :DWORD
       LOCAL	hGlobal:HGLOBAL
       LOCAL	hdc:HDC
       LOCAL	pGlobal:PTSTR
       LOCAL    ps:PAINTSTRUCT
       LOCAL    rect:RECT

	.if	uMsg == WM_CREATE
		invoke	SetClipboardViewer,hwnd
		mov	hwndNextViewer,eax

		xor	eax,eax
		ret	
	.elseif	uMsg == WM_CHANGECBCHAIN
		mov	eax,wParam
		.if	eax == hwndNextViewer
			mov	eax,lParam
			mov	hwndNextViewer,eax
		.else
			.if	hwndNextViewer!=0
				invoke	SendMessage,hwndNextViewer, uMsg, wParam, lParam
			.endif
		.endif	

		xor	eax,eax
		ret			
	.elseif	uMsg == WM_DRAWCLIPBOARD
		.if	hwndNextViewer != 0
			invoke	SendMessage,hwndNextViewer, uMsg, wParam, lParam
		.endif	
		invoke	InvalidateRect,hwnd, NULL, TRUE

		xor	eax,eax
		ret

	.elseif uMsg == WM_PAINT
              invoke	BeginPaint,hwnd,addr ps
              mov	hdc,eax 
              invoke	GetClientRect,hwnd,addr rect
 	      invoke	OpenClipboard,hwnd	
 	      invoke	GetClipboardData,CF_TEXT
	      mov	hGlobal,eax
              .if 	hGlobal != NULL
              		invoke	GlobalLock,hGlobal
                        mov	pGlobal,eax
        		invoke	DrawText,hdc, pGlobal, -1, addr rect, DT_EXPANDTABS
        		invoke	GlobalUnlock,hGlobal
              .endif
	      invoke	CloseClipboard
      	      invoke	EndPaint,hwnd,addr ps
        
	      xor	eax,eax
	      ret
	.elseif uMsg == WM_DESTROY
		invoke	ChangeClipboardChain,hwnd, hwndNextViewer

	        invoke 	PostQuitMessage,NULL
	        xor	eax,eax
	        ret
	.endif

	invoke DefWindowProc,hwnd,uMsg,wParam,lParam
	ret
WndProc endp
END START


 



运行结果

CLIPVIEW依上面所讨论的方法来处理WM_CREATE、WM_CHANGECBCHAIN、WM_DRAWCLIPBOARD和WM_DESTROY消息。WM_PAINT消息处理打开剪切板,并用CF_TEXT格式呼叫GetClipboardData。如果函数传回一个整体内存句柄,那么CLIPVIEW将锁定它,并用DrawText在显示区域显示文字。

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

WM_PAINTCLIPBOARD
WM_SIZECLIPBOARD
 WM_VSCROLLCLIPBOARD
WM_HSCROLLCLIPBOARD
 

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

上面学习了剪切板的使用,最后,我这里还有一个创意提供给各位读者,有兴趣的可以在下面试验一下,这个是完全可以做到的,我用Delphi已经轻松的实现了。

现在的MP3容量越来越大,我在使用MP3听评书的时候发现了一个问题:拷贝进去的歌曲无法控制顺序,就是你选中N多歌曲,用拷贝粘贴的方式丢在MP3里面,播放出来的通常会混乱。“三顾茅庐”会排在“草船借箭”的后面。经过考察发现,歌曲的顺序是又声音文件在MP3 FAT中的顺序决定的。而FAT中排列的顺序是又拷贝进去的先后顺序决定的。拷贝进去的先后顺序则是剪切板中的顺序决定的。

下面的不说了。



--------------------------------------------------------------------------------
<<<上一篇  欢迎访问AoGo汇编小站:http://www.aogosoft.com  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -