📄 xp.asm
字号:
invoke LoadImage,hInstance,lpDrawInfo.itemID,IMAGE_ICON,16,16,LR_LOADMAP3DCOLORS or LR_SHARED
.if eax != 0 ; 绘制图标
mov hMenuIcon,eax
invoke MemCopy,addr lpDrawInfo.rcItem,addr rct,sizeof rct
add rct.left,4
add rct.top,2
.if byte ptr lpDrawInfo.itemState & ODS_GRAYED
invoke DrawState,lpDrawInfo.hdc,0,0,hMenuIcon,0,rct.left,rct.top,16,16,DST_ICON or DSS_DISABLED
.else
invoke DrawIconEx,lpDrawInfo.hdc,rct.left,rct.top,hMenuIcon,16,16,0,0,DI_NORMAL
.endif
invoke DeleteObject,hMenuIcon
.endif
.if lpDrawInfo.itemState & MFS_DEFAULT || lpDrawInfo.itemID == SC_CLOSE
mov ecx,FW_BOLD ; 默认菜单或关闭菜单设置为粗体
.else
mov ecx,FW_NORMAL
.endif
szText szFontSimun,"宋体"
invoke CreateFont,0FFFFFFF4H,0,0,0,ecx,0,0,0,GB2312_CHARSET,0,0,0,0,addr szFontSimun
mov hMenuFont,eax
invoke SelectObject,lpDrawInfo.hdc,hMenuFont
mov hBakFont,eax
invoke GetMenuString,lpDrawInfo.itemData,lpDrawInfo.itemID,addr szMenuText,sizeof szMenuText,MF_BYCOMMAND
lea esi,szMenuText ; 获取菜单中在09控制符前面的文字
lea edi,hOutBuffer
.while byte ptr [esi] != 9 && byte ptr [esi] != 0
lodsb
stosb
.endw
xor al,al
stosb
invoke MemCopy,addr lpDrawInfo.rcItem,addr rct,sizeof rct
inc rct.top
inc rct.bottom
.if byte ptr lpDrawInfo.itemState & ODS_GRAYED
;invoke GetSysColor,COLOR_GRAYTEXT ; 设置菜单文本禁用状态的颜色
mov eax,8F888Fh
.else
.if byte ptr lpDrawInfo.itemState & ODS_SELECTED
invoke GetSysColor,COLOR_CAPTIONTEXT ; 设置菜单文本颜色高亮
.else
invoke GetSysColor,COLOR_MENUTEXT ; 设置菜单文本颜色为默认
.endif
.endif
invoke SetTextColor,lpDrawInfo.hdc,eax ; 开始设置菜单文本颜色
.if lpDrawInfo.itemID == SC_CLOSE || lpDrawInfo.itemID == SC_RESTORE || lpDrawInfo.itemID == SC_MINIMIZE || lpDrawInfo.itemID == SC_MAXIMIZE
mov rct.left,5 ; 设置菜单文本起始位置
szText szFontChar,"Marlett" ; 绘制系统菜单上的助记符
szText szRestoreChar,"2"
szText szMinimizeChar,"0"
szText szMaximizeChar,"1"
szText szCloseChar,"r"
invoke CreateFont,13,0,0,0,0,0,0,0,SYMBOL_CHARSET,0,0,0,0,addr szFontChar
mov hCyleFont,eax
invoke SelectObject,lpDrawInfo.hdc,eax
mov hBkFont,eax
.if lpDrawInfo.itemID == SC_RESTORE
lea ecx,szRestoreChar ; 绘制系统菜单“恢复”的助记符
.elseif lpDrawInfo.itemID == SC_MINIMIZE
lea ecx,szMinimizeChar ; 绘制系统菜单“最小化”的助记符
.elseif lpDrawInfo.itemID == SC_MAXIMIZE
lea ecx,szMaximizeChar ; 绘制系统菜单“最大化”的助记符
.elseif lpDrawInfo.itemID == SC_CLOSE
lea ecx,szCloseChar ; 绘制系统菜单“关闭”的助记符
.endif
invoke DrawText,lpDrawInfo.hdc,ecx,-1,addr rct,DT_VCENTER+DT_SINGLELINE
invoke SelectObject,lpDrawInfo.hdc,hBkFont
invoke DeleteObject,hCyleFont
mov rct.left,26
.if lpDrawInfo.itemID == SC_CLOSE
dec rct.left
.endif
.else
mov rct.left,26
.endif
; 绘制菜单中在09控制符前面的文字
invoke DrawText,lpDrawInfo.hdc,addr hOutBuffer,-1,addr rct,DT_VCENTER+DT_SINGLELINE
lodsb
.if al == 9
sub rct.right,20 ; 绘制菜单中在09控制符后面的文字
invoke DrawText,lpDrawInfo.hdc,esi,-1,addr rct,DT_VCENTER+DT_SINGLELINE+DT_RIGHT
.endif
.if byte ptr lpDrawInfo.itemState & MFS_CHECKED ; 绘制菜单上的复选标记
invoke MemCopy,addr lpDrawInfo.rcItem,addr rct,sizeof rct
inc rct.top
add rct.left,3
mov eax,rct.left
mov ebx,rct.top
mov edx,rct.bottom
mov ecx,edx
sub ecx,rct.top
add ecx,eax
;invoke AddSubRect,addr rct,1
invoke SetRect,addr rct,eax,ebx,ecx,edx
invoke InflateRect,addr rct,-5,-5
invoke CreateSolidBrush,0c8a0a4h
mov hBrush,eax
invoke FillRect,lpDrawInfo.hdc,addr rct,hBrush
invoke DeleteObject,hBrush
invoke InflateRect,addr rct,1,1
invoke DrawEdge,lpDrawInfo.hdc,addr rct,BDR_SUNKENOUTER,BF_RECT or BF_MONO or BF_ADJUST
invoke InflateRect,addr rct,3,4
invoke GetSysColor,COLOR_MENUTEXT
invoke SetTextColor,lpDrawInfo.hdc,eax
szText szCheck,"√" ; 绘制菜单的复选框
invoke CreateFont,0FFFFFFF1H,0,0,0,0,0,0,0,GB2312_CHARSET,0,0,0,0,addr szFontSimun
mov hCyleFont,eax
invoke SelectObject,lpDrawInfo.hdc,eax
mov hBkFont,eax
invoke DrawText,lpDrawInfo.hdc,addr szCheck,-1,addr rct,DT_VCENTER or DT_SINGLELINE
invoke SelectObject,lpDrawInfo.hdc,hBkFont
invoke DeleteObject,hCyleFont
.endif
invoke SelectObject,lpDrawInfo.hdc,hBakFont
invoke DeleteObject,hMenuFont
invoke SetTextColor,lpDrawInfo.hdc,hTxtColor
invoke SetBkColor,lpDrawInfo.hdc,hBakColor
invoke SetBkMode,lpDrawInfo.hdc,hBakMode
m2m eax,1
ret
DrawMenuItem endp
; 设置菜单高度和宽度
ModifyXPMenu proc uses esi edi ebx,hWin:DWORD,lParam:DWORD
LOCAL hdc:DWORD
LOCAL hMenuFont:DWORD,hBakFont:DWORD
LOCAL rct:RECT
LOCAL szMenuText[100]:BYTE
LOCAL hOutBuffer[100]:BYTE
mov ebx,lParam
.if [ebx.MEASUREITEMSTRUCT].CtlType == ODT_MENU
invoke GetSystemMetrics,SM_CYMENU
.if [ebx.MEASUREITEMSTRUCT].itemID == 0 || [ebx.MEASUREITEMSTRUCT].itemID == -1
xor edx,edx
mov ecx,2
div ecx
.endif ; 设置菜单高度
mov [ebx.MEASUREITEMSTRUCT].itemHeight,eax
mov esi,[ebx.MEASUREITEMSTRUCT].itemID
invoke GetDC,hWin
mov hdc,eax
invoke CreateFont,0FFFFFFF4H,0,0,0,0,0,0,0,GB2312_CHARSET,0,0,0,0,addr szFontSimun
mov hMenuFont,eax
invoke SelectObject,hdc,hMenuFont
mov hBakFont,eax ; 获取菜单字符
invoke GetMenuString, [ebx.MEASUREITEMSTRUCT].itemData,esi,addr szMenuText,sizeof szMenuText,MF_BYCOMMAND
lea esi,szMenuText
lea edi,hOutBuffer
mov ecx,6
mov al," "
rep stosb
.repeat
lodsb
.if al == 9 ; 在09控制符间插入几个空格
mov al," "
mov ecx,3
rep stosb
.continue
.endif
stosb
.until al == 0 ; 计算菜单宽度
invoke DrawText,hdc,addr hOutBuffer,-1,addr rct,DT_LEFT+DT_SINGLELINE+DT_CALCRECT
invoke SelectObject,hdc,hBakFont
invoke DeleteObject,hMenuFont
invoke ReleaseDC,hWin,hdc
mov eax,rct.right
sub eax,rct.left
mov ecx,lParam
mov [ecx.MEASUREITEMSTRUCT].itemWidth,eax
.endif
m2m eax,1
ret
ModifyXPMenu endp
; 控制右键弹出的编辑菜单
ControlMenu proc uses ebx,hWin:DWORD
LOCAL rct :RECT
LOCAL pt :POINT
LOCAL hRightMenu:DWORD
invoke CreateRightMenu
mov hRightMenu,eax
invoke InitXPMenu,hRightMenu
invoke SendMessage,hWin,EM_CANUNDO,0,0
.if eax == TRUE ; 判断是否能撤消
push MF_ENABLED
.else
push MF_GRAYED
.endif
pop eax
invoke EnableMenuItem,hRightMenu,WM_UNDO,eax
invoke OpenClipboard,hWin
invoke IsClipboardFormatAvailable,eax
.if eax == TRUE ; 判断剪贴板是否有数据可粘贴
push MF_ENABLED
.else
push MF_GRAYED
.endif
pop eax
invoke EnableMenuItem,hRightMenu,WM_PASTE,eax
invoke CloseClipboard
invoke SendMessage,hWin,EM_GETSEL,0,0
movzx ecx,ax
shr eax,16
push eax
push ecx
.if eax == ecx ; 判断是否选中了文本
push MF_GRAYED
.else
push MF_ENABLED
.endif
pop ebx
invoke EnableMenuItem,hRightMenu,WM_CUT,ebx
invoke EnableMenuItem,hRightMenu,WM_COPY,ebx
invoke EnableMenuItem,hRightMenu,WM_CLEAR,ebx
invoke GetWindowTextLength,hWin
pop ecx
pop ebx
.if eax == ebx && ecx == 0 ; 判断是否选中了全部文本
push MF_GRAYED
.else
push MF_ENABLED
.endif
pop eax
invoke EnableMenuItem,hRightMenu,EM_SETSEL,eax
invoke ShowRightMenu,hWin,hRightMenu
invoke DestroyMenu,hRightMenu
m2m eax,1
ret
ControlMenu endp
InitXPMenu proc uses esi ebx,hBmpMenu
LOCAL hMenuIndex:DWORD
LOCAL hSubMenuIndex:DWORD
LOCAL hSubMenuHandle:DWORD
invoke GetMenuItemCount,hBmpMenu
.if eax == -1
ret
.endif
mov hMenuIndex,eax
xor ebx,ebx
.while ebx < hMenuIndex
invoke GetSubMenu,hBmpMenu,ebx
.if eax == 0
invoke GetMenuItemID,hBmpMenu,ebx
mov ecx,MF_OWNERDRAW or MF_BYPOSITION
.if eax == 0 || eax == -1
or ecx,MF_SEPARATOR
.endif ; 修改菜单为所有者绘制
invoke ModifyMenu,hBmpMenu,ebx,ecx,eax,hBmpMenu
.else
mov hSubMenuHandle,eax
invoke GetMenuItemCount,hSubMenuHandle
.if eax != -1
mov hSubMenuIndex,eax
xor esi,esi
.while esi < hSubMenuIndex
invoke GetMenuItemID,hSubMenuHandle,esi
mov ecx,MF_OWNERDRAW or MF_BYPOSITION
.if eax == 0 || eax == -1
or ecx,MF_SEPARATOR
.endif ; 修改菜单为所有者绘制
invoke ModifyMenu,hSubMenuHandle,esi,ecx,eax,hBmpMenu
inc esi
.endw
m2m eax,1
.else
xor eax,eax
.endif
.endif
inc ebx
.endw
ret
InitXPMenu endp
; 右键弹出的控制菜单(只读)
DrawReadOnlyEdit proc uses esi edi ebx,hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
LOCAL hRightMenu:DWORD
mov eax,uMsg
.if eax == WM_COMMAND
invoke ControlCommand,hWin,wParam
ret
.elseif eax == WM_KEYDOWN
movzx eax,byte ptr wParam ; 判断是否按下了CTRL+C
.if eax == VK_DELETE
m2m eax,1
ret
.endif
.elseif eax == WM_CHAR
movzx eax,byte ptr wParam
.if al == 3 || al == VK_HOME || al == VK_END || al == VK_LEFT || al == VK_RIGHT || al == VK_CONTROL || al == VK_SHIFT
.else
m2m eax,1
ret
.endif
.elseif eax == WM_CONTEXTMENU
invoke CreateRightMenu
mov hRightMenu,eax
invoke InitXPMenu,hRightMenu
invoke EnableMenuItem,hRightMenu,WM_UNDO,MF_GRAYED
invoke EnableMenuItem,hRightMenu,WM_CUT,MF_GRAYED
invoke EnableMenuItem,hRightMenu,WM_PASTE,MF_GRAYED
invoke EnableMenuItem,hRightMenu,WM_CLEAR,MF_GRAYED
invoke SendMessage,hWin,EM_GETSEL,0,0
movzx ecx,ax
shr eax,16
push eax
push ecx
.if eax == ecx ; 判断是否选中了文本
push MF_GRAYED
.else
push MF_ENABLED
.endif
pop eax
invoke EnableMenuItem,hRightMenu,WM_COPY,eax
invoke GetWindowTextLength,hWin
pop ecx
pop ebx
.if eax == ebx && ecx == 0 ; 判断是否选中了全部文本
push MF_GRAYED
.else
push MF_ENABLED
.endif
pop eax
invoke EnableMenuItem,hRightMenu,EM_SETSEL,eax
invoke ShowRightMenu,hWin,hRightMenu
invoke DestroyMenu,hRightMenu
m2m eax,1
ret
.elseif eax == WM_DRAWITEM
mov eax,lParam
.if [eax.DRAWITEMSTRUCT].CtlType == ODT_MENU
invoke DrawMenuItem,lParam ; 绘制菜单
.endif
ret
.elseif eax == WM_MEASUREITEM
invoke ModifyXPMenu,hWin,lParam ; 设置菜单高度和宽度
ret
.elseif eax == EM_SETREADONLY
.if wParam == FALSE
invoke SetWindowLong,hWin,GWL_WNDPROC,addr DrawReadWriteEdit
.endif
.endif
invoke GetWindowLong,hWin,GWL_USERDATA
invoke CallWindowProc,eax,hWin,uMsg,wParam,lParam
ret
DrawReadOnlyEdit endp
CreateRightMenu proc
LOCAL hRightMenu:DWORD
invoke CreatePopupMenu
mov hRightMenu,eax
szText szUndoString,"撤消(&U)"
szText szCutString,"剪切(&T)"
szText szCopyString,"复制(&C)"
szText szPasteString,"粘贴(&P)"
szText szDelString,"删除(&D)"
szText szSelectString,"全选(&A)"
invoke AppendMenu,hRightMenu,MF_STRING,WM_UNDO,addr szUndoString
invoke AppendMenu,hRightMenu,MF_SEPARATOR,-1,0
invoke AppendMenu,hRightMenu,MF_STRING,WM_CUT,addr szCutString
invoke AppendMenu,hRightMenu,MF_STRING,WM_COPY,addr szCopyString
invoke AppendMenu,hRightMenu,MF_STRING,WM_PASTE,addr szPasteString
invoke AppendMenu,hRightMenu,MF_STRING,WM_CLEAR,addr szDelString
invoke AppendMenu,hRightMenu,MF_SEPARATOR,-1,0
invoke AppendMenu,hRightMenu,MF_STRING,EM_SETSEL,addr szSelectString
mov eax,hRightMenu
ret
CreateRightMenu endp
; 弹出右键菜单
ShowRightMenu proc hWin:DWORD,lpMenu:DWORD
LOCAL rct :RECT
LOCAL pt :POINT
invoke SetFocus,hWin
invoke GetCursorPos,addr pt
invoke GetWindowRect,hWin,addr rct
invoke PtInRect,addr rct,pt.x,pt.y
.if eax == FALSE
mov eax,rct.bottom
sub eax,rct.top
shr eax,1
add rct.top,eax
mov eax,rct.right
sub eax,rct.left
shr eax,1
add rct.left,eax
invoke TrackPopupMenu,lpMenu,TPM_LEFTALIGN,rct.left,rct.top,0,hWin,0
.else
invoke TrackPopupMenu,lpMenu,TPM_LEFTALIGN,pt.x,pt.y,0,hWin,0
.endif
ret
ShowRightMenu endp
; 初使化子窗口中的系统菜单
InitSubSystemMenu proc hWin:DWORD
LOCAL lpmii:MENUITEMINFO
LOCAL hSubSysMenu:DWORD
invoke GetSystemMenu,hWin,0
mov hSubSysMenu,eax
invoke DeleteMenu,hSubSysMenu,SC_CLOSE,MF_BYCOMMAND
.if eax != 0
szText hMenuSubClose,"关闭(&C) Alt+F4"
invoke MemFill,addr lpmii,sizeof lpmii
mov lpmii.cbSize,sizeof lpmii
mov lpmii.fMask,MIIM_STRING or MIIM_ID
mov lpmii.wID,SC_CLOSE
mov lpmii.dwTypeData,offset hMenuSubClose
invoke InsertMenuItem,hSubSysMenu,-1,TRUE,addr lpmii
.endif
invoke InitXPMenu,hSubSysMenu
ret
InitSubSystemMenu endp
; 清空内存
MemFill proc uses edi,lpMem:DWORD,lpSize:DWORD
mov edi,lpMem
mov ecx,lpSize
xor al,al
rep stosb
ret
MemFill endp
; 显示子窗口中右键弹出的系统菜单
PopupSubSystemMenu proc uses ebx,hWin:DWORD,lParam:DWORD
LOCAL pt :POINT
LOCAL rct :RECT
lea ebx,lParam
.if [ebx.POINTS].y < 30
invoke GetClientRect,hWin,addr rct
mov eax,rct.right
sub eax,26
.if [ebx.POINTS].x < ax
invoke GetCursorPos,addr pt
invoke GetSystemMenu,hWin,0
invoke TrackPopupMenu,eax,TPM_LEFTALIGN,pt.x,pt.y,0,hWin,0
.endif
.endif
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -