帖一下代码罢
程序代码:
;MASMPlus 代码模板 - 普通的 Windows 程序代码
;*****************************************************************************************************************
;作者:zklhp
;Email:zklhp@最后更新:2009.12.27
;版权所有 转载请保持完整
;*****************************************************************************************************************
.386
.Model Flat, StdCall
Option Casemap :None
Include windows.inc
Include user32.inc
Include kernel32.inc
Include shell32.inc
Include gdi32.inc
Include user32.inc
includelib gdi32.lib
IncludeLib user32.lib
IncludeLib kernel32.lib
IncludeLib user32.lib
IncludeLib shell32.lib
include macro.asm
include rsrc.inc
WM_SHELLNOTIFY equ WM_USER+5
IDI_TRAY equ 0
IDM_ABOUT equ 1000
IDM_EXIT equ 1010
IDM_HELP equ 1020
IDM_SETTING equ 1030
;0 - 0BFFFh
WIN0 EQU 9
WIN1 EQU 0
WIN2 EQU 1
WIN3 EQU 2
WIN4 EQU 3
WIN5 EQU 4
WIN6 EQU 5
WIN7 EQU 6
WIN8 EQU 7
WIN9 EQU 8
NEWDESKTOP struct
hDesktop dd ?
fIsShell dd ? ;TRUE为已运行explorer
NEWDESKTOP ends
;IE6及以上版本的 NOTIFYICONDATA 结构和常量
NOTIFYICONDATA_ struct
cbSize DWORD ?
hwnd DWORD ?
uID DWORD ?
uFlags DWORD ?
uCallbackMessage DWORD ?
hIcon DWORD ?
szTip BYTE 128 dup (?)
dwState DWORD ?
dwStateMask DWORD ?
szInfo BYTE 256 dup (?)
union
uTimeout DWORD ?
uVersion DWORD ?
ends
szInfoTitle BYTE 64 dup (?)
dwInfoFlags DWORD ?
GuidItem GUID <?>
NOTIFYICONDATA_ ends
NIF_INFO equ 010h
NIIF_INFO equ 01h
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
.data
dwNewDesktopNum dd 1 ;新建桌面数
szClassName db 'MD_TrayIconWinClass',0
szAppName db 'Multi-Desktop v0.1',0
szSettingString db '&Setting',0
szAboutString db '&About',0
szHelpString db '&Help',0
szFmtDesktopNum db '现在共有%d个桌面',0
szAboutText db 'Multi-Desktop v0.1',0dh,0ah,'By zklhp',0dh,0ah,'Email:zklhp@',0dh,0ah
db '版权所有 转载请保持完整 谢谢!',0
szHelpText db '程序默认建立一个桌面 可通过快捷键WIN+1访问 WIN+`(`是键盘1前面那个)为当前桌面',0dh,0ah
db '桌面的个数可以通过设置改变 最大支持新建9个桌面',0dh,0ah,'切换到新建桌面的快捷键将按 WIN+1 WIN+2 WIN+3 依次递增',0dh,0ah
db '不推荐频繁改变新建桌面数 为什么自己试试就知道了 也不推荐重复运行(就是关了再开)本程序',0
szExitString db 'E&xit Program',0
szInitInfo db 'Multi-Desktop已启动 现在您可以切换到其他桌面 默认建立一个桌面 可通过快捷键WIN+1访问 如果您不会使用请查看帮助~',0
.data?
hMutex dd ?
hInstance dd ?
hWinMain dd ?
hPopupMenu dd ?
note NOTIFYICONDATA_ <>
stDesktop NEWDESKTOP 8 dup(<>)
hCurrentDesktop dd ?
dwMsgTaskbarRestart dd ?
szBuf db 64 dup(?)
.CODE
start:
;为防止有多个进程同时运行 使用互斥体判断
;是否有运行标志
invoke CreateMutex,NULL,FALSE,CTXT('MD_RUNNING')
mov hMutex,eax
invoke GetLastError
.if eax == ERROR_ALREADY_EXISTS ;有则退出
invoke ExitProcess,0
.endif
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke WinMain,hInstance,NULL,NULL,SW_HIDE
invoke ExitProcess,eax
_CreateDesktop proc uses edi esi _lpParam:DWORD
xor edi,edi
lea esi,stDesktop
assume esi:ptr NEWDESKTOP
.while edi < dwNewDesktopNum
invoke wsprintf,offset szBuf,CTXT('MD_Desktop%d'),edi ;MD_Desktop0 到 MD_Desktop8
invoke OpenDesktop,offset szBuf,0,FALSE,0 ;看桌面是否已经存在
.if !eax
invoke CloseDesktop,eax ;存在则先关闭
.endif
invoke CreateDesktop,offset szBuf,NULL,NULL,0,GENERIC_ALL,NULL
.if eax
mov [esi].hDesktop,eax
mov [esi].fIsShell,FALSE ;对重复运行无效
;invoke SetThreadDesktop,eax ;这个不知道干什么用的 貌似注释了也可以用~
.endif
add esi,sizeof NEWDESKTOP
inc edi
.endw
assume esi:NOTHING
ret
_CreateDesktop endp
WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
local @stWndClass:WNDCLASSEX
local @stMsg:MSG
invoke RtlZeroMemory, addr @stWndClass, sizeof @stWndClass
invoke LoadCursor, 0, IDC_ARROW
mov @stWndClass.hCursor, eax
mov eax, hInstance
mov @stWndClass.hInstance, eax
mov @stWndClass.cbSize, sizeof WNDCLASSEX
mov @stWndClass.lpfnWndProc, offset WndProc
mov @stWndClass.hbrBackground, COLOR_WINDOW + 1
mov @stWndClass.lpszClassName, offset szClassName
invoke RegisterClassEx, addr @stWndClass
;创建无标题栏的窗口
invoke CreateWindowEx, WS_EX_TOOLWINDOW, addr szClassName,NULL, WS_POPUP or WS_SYSMENU, 0, 0, 0, 0,NULL, NULL, hInstance, NULL
mov hWinMain, eax
invoke ShowWindow, hWinMain, SW_SHOWNORMAL
invoke UpdateWindow, hWinMain
.while TRUE
invoke GetMessage, addr @stMsg, NULL, 0, 0
.break .if eax == 0
invoke TranslateMessage, addr @stMsg
invoke DispatchMessage, addr @stMsg
.endw
ret
WinMain endp
DlgProc proc hWnd,uMsg,wParam,lParam
.if uMsg==WM_INITDIALOG
invoke LoadIcon,hInstance,ICON_168
mov eax,dwNewDesktopNum
invoke SetDlgItemInt,hWnd,IDC_EDT1,eax,FALSE
.elseif uMsg==WM_COMMAND
mov eax,wParam
and eax,0ffffh
.if eax==IDOK
invoke SendMessage,hWnd,WM_COMMAND,IDC_BTN1,0 ;按回车是确定
.elseif eax==IDCANCEL
invoke SendMessage,hWnd,WM_CLOSE,0,0 ;按ESC退出
.elseif eax==IDC_BTN1 ;确定
invoke GetDlgItemInt,hWnd,IDC_EDT1,FALSE,FALSE
.if eax < 10 && eax >0
mov dwNewDesktopNum,eax
invoke SendMessage,hWnd,WM_CLOSE,0,0
.endif
.elseif eax==IDC_BTN2 ;取消
invoke SendMessage,hWnd,WM_CLOSE,0,0
.endif
.elseif uMsg==WM_CLOSE
invoke EndDialog,hWnd,wParam
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
local pt:POINT
local @stStartInfo:STARTUPINFO
local @stProcessInfo:PROCESS_INFORMATION
mov eax,uMsg
.if uMsg==WM_CREATE
;得到当前桌面
invoke GetCurrentThreadId
invoke GetThreadDesktop,eax
mov hCurrentDesktop,eax
invoke SetWindowPos,hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE ;窗口置顶
invoke RegisterHotKey,hWnd,WIN0,MOD_WIN,VK_OEM_3 ;WIN+` VK_OEM_3 是 C0 不同的头文件有可能不同 就是1前面那个~
invoke CreatePopupMenu
mov hPopupMenu,eax
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_ABOUT,addr szAboutString
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_HELP,addr szHelpString
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_SETTING,addr szSettingString
invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr szExitString
mov note.cbSize,sizeof NOTIFYICONDATA_
push hWnd
pop note.hwnd
mov note.uID,IDI_TRAY
mov note.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP
mov note.uCallbackMessage,WM_SHELLNOTIFY
invoke LoadIcon,hInstance,ICON_168
mov note.hIcon,eax
invoke lstrcpy,addr note.szTip,offset szAppName
invoke Shell_NotifyIcon,NIM_ADD,addr note
push ecx
invoke CreateThread,0,0,offset _CreateDesktop,0,0,esp
pop ecx
xor edi,edi
.while edi < dwNewDesktopNum
mov eax,edi
add eax,031h
invoke RegisterHotKey,hWnd,edi,MOD_WIN,eax ;WIN+1 到 WIN+9
inc edi
.endw
invoke lstrcpy,addr note.szInfo,offset szInitInfo
invoke lstrcpy,addr note.szInfoTitle,offset szAppName
mov eax,note.uFlags
or eax,NIF_INFO
mov note.uFlags,eax
mov note.uTimeout,20d
mov note.dwInfoFlags,NIIF_INFO
invoke Shell_NotifyIcon,NIM_MODIFY,addr note
;防止外壳后图标消失
invoke RegisterWindowMessage,CTXT('TaskbarCreated')
mov dwMsgTaskbarRestart,eax
.elseif eax==dwMsgTaskbarRestart ;只能用这个笨办法了 赋给eax再比
mov note.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP
invoke Shell_NotifyIcon,NIM_ADD,addr note
or note.uFlags,NIF_INFO
mov eax,dwNewDesktopNum
inc eax
invoke wsprintf,addr note.szInfo,offset szFmtDesktopNum,eax
invoke Shell_NotifyIcon,NIM_MODIFY,addr note
.elseif uMsg==WM_DESTROY
invoke DestroyMenu,hPopupMenu
;切回原来的
invoke SwitchDesktop,hCurrentDesktop
invoke UnregisterHotKey,hWnd,WIN0
xor edi,edi
.while edi < dwNewDesktopNum
invoke UnregisterHotKey,hWnd,edi
invoke wsprintf,offset szBuf,CTXT('MD_Desktop%d'),edi ;MD_Desktop0 到 MD_Desktop8
;关掉已新建的桌面
;桌面关了 但这个桌面的程序还在 所以 下次再有和这个名字相同的桌面时那些窗口应该还在
;所以 可能会多一堆 我的文档 一类的窗口 故而 本程序一次只能运行一个 且不推荐改变桌面数
invoke OpenDesktop,offset szBuf,0,FALSE,0
.if !eax
invoke CloseDesktop,eax
.endif
inc edi
.endw
invoke Shell_NotifyIcon,NIM_DELETE,addr note
invoke PostQuitMessage,NULL
.elseif uMsg==WM_COMMAND
.if lParam==0
mov eax,wParam
.if ax==IDM_ABOUT
invoke GetDesktopWindow
invoke MessageBox,eax,offset szAboutText,offset szAppName,0
.elseif ax ==IDM_EXIT
invoke DestroyWindow,hWnd
.elseif ax ==IDM_HELP
invoke GetDesktopWindow
invoke MessageBox,eax,offset szHelpText,offset szAppName,0
.elseif ax ==IDM_SETTING
invoke DialogBoxParam,hInstance,IDD_DLG1,0,offset DlgProc,0
;必须保证新建的线程在当前桌面没有窗口 在“干净”的线程中最好
;不用线程ID 随便放
push ecx
invoke CreateThread,0,0,offset _CreateDesktop,0,0,esp
pop ecx
mov eax,dwNewDesktopNum
inc eax
invoke wsprintf,addr note.szInfo,offset szFmtDesktopNum,eax
invoke Shell_NotifyIcon,NIM_MODIFY,addr note
.endif
.endif
.elseif uMsg==WM_SHELLNOTIFY
.if wParam==IDI_TRAY
.if lParam==WM_RBUTTONDOWN
invoke GetCursorPos,addr pt
invoke SetForegroundWindow,hWnd
invoke TrackPopupMenu,hPopupMenu,TPM_RIGHTALIGN,pt.x,pt.y,NULL,hWnd,NULL
invoke PostMessage,hWnd,WM_NULL,0,0
.elseif lParam==WM_LBUTTONDOWN
invoke SendMessage,hWnd,WM_COMMAND,IDM_ABOUT,0
.endif
.endif
.elseif uMsg==WM_HOTKEY
.if wParam == WIN0
invoke SwitchDesktop,hCurrentDesktop
.elseif wParam >= WIN1 && wParam <= WIN9
mov edi,wParam
lea esi,stDesktop
assume esi:ptr NEWDESKTOP
imul ebx,edi,sizeof NEWDESKTOP
mov eax,[esi+ebx].hDesktop
invoke SwitchDesktop,eax
.if [esi+ebx].fIsShell == FALSE
invoke wsprintf,offset szBuf,CTXT('MD_Desktop%d'),edi ;MD_Desktop0 到 MD_Desktop8
mov @stStartInfo.cb,sizeof STARTUPINFO
lea ecx,szBuf
mov @stStartInfo.lpDesktop,ecx
mov @stStartInfo.dwFlags,STARTF_USESHOWWINDOW
mov @stStartInfo.wShowWindow,SW_SHOWNORMAL
;如果多次执行则会产生一堆 我的文档 一类的窗口
invoke CreateProcess,NULL,CTXT('explorer'),NULL,NULL,TRUE,NULL,NULL,NULL,addr @stStartInfo,addr @stProcessInfo
;这两个句柄不用就关
invoke CloseHandle,@stProcessInfo.hProcess
invoke CloseHandle,@stProcessInfo.hThread
mov [esi+ebx].fIsShell,TRUE
.endif
assume esi:NOTHING
.endif
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WndProc endp
end start