用WIN汇编开发桌面报时工具

用WIN32汇编语言开发出来的WINDOWS程序具有执行效率高、占用空间小等特点。

一、  软件简介及相应开发工具

桌面报时工具主要完成以下两个功能:

1、     F12热键语音报时、语音整点报时。

2、  在屏幕中上方直接显示时间,并不被任何窗口挡住。

3、  程序运行后最小化为任务栏图标。

笔者以WIN汇编为开发语言,以MASM32为开发工具,因为它不但可以免费获取和使用,而且自带IDE编程环境,读者可访问其官方网站下载MASM32开发包,官方网站为:http://www.movsd.com/。

二、设计思路

1、软件采用标准的自定义对话框架构实现。

2、采用微软的TTS语音引擎实现语音报时。 TTS基于COM,因此开发使用Microsoft SpeechSDK,直接调用SAPI实现语音朗读。

3、使用HOOK技术,截获F12按键进行语音报时。因此,笔者单独编写了一个DLL文件,捕捉F12按键。

由此可见,该报时工具虽小,但五脏俱全,涉及对话框消息循环、HOOK技术、COM接口、DLL文件编写、主要API的调用等技术。

三、实现代码

1、主程序代码

.586

.model flat, stdcall

option casemap :none

;#########################################################################

;首先声明头文件

include windows.inc

include user32.inc

include kernel32.inc

include gdi32.inc

include masm32.inc

include shell32.inc

include ole32.inc

include d:\masm32\com\include\oaidl.inc

include timersdll.inc

includelib user32.lib

includelib kernel32.lib

includelibgdi32.lib

includelib masm32.lib

includelib shell32.lib

includelib ole32.lib

includelib timersdll.lib

;#########################################################################

;声明宏(主要是控件ID和菜单ID)

IDC_ALARM equ 101

IDC_CANCEL equ 102

IDC_OK equ 103

IDC_ABOUT equ 104

IDC_CHECKBS equ 105

IDC_CHECKSHOWTIMER equ 106

IDR_MAINFRAME equ 107

IDR_MAINMENU equ 108

MENUID_SYSTEMSET equ 109

MENUID_SPEAKTIMER equ 110

MENUID_ABOUT equ 111

MENUID_EXIT equ 112

DIALOG_MAIN equ 1

IDT_TIMER equ 1

WM_NOTIFYICONN equ WM_USER+0

WM_CLOCKALARM equWM_USER+100h

;#########################################################################

;Microsoft Speech SDK没有相应的适应于汇编语言的INC头文件,笔者在代码

;文件中直接声明TTS相关虚函数。

;定义ISpVoice的虚函数接口表(根据SDK中的sapi.h中ISpVoiceVtbl的C++定义改

;成MASM32定义)

ISpVoice STRUCT DWORD

QueryInterface comethod3 ?

AddRef comethod1 ?

Release  comethod1 ?

SetNotifySink comethod2 ?

SetNotifyWindowMessage  comethod5 ?

SetNotifyCallbackFunction  comethod4 ?

SetNotifyCallbackInterface  comethod4 ?

SetNotifyWin32Event comethod1 ?

WaitForNotifyEvent comethod1 ?

GetNotifyEventHandle  comethod1 ?

SetInterest  comethod3 ?

GetEvents  comethod4 ?

GetInfo comethod2 ?

SetOutput  comethod3 ?

GetOutputObjectToken comethod2 ?

GetOutputStream comethod2 ?

Pause comethod1 ?

Resume comethod1 ?

SetVoice comethod2 ?

GetVoice comethod2 ?

Speak  comethod4 ?

SpeakStream comethod4 ?

GetStatus  comethod3 ?

Skip comethod4 ?

SetPriority comethod2 ?

GetPriority comethod2 ?

SetAlertBoundary comethod2 ?

GetAlertBoundary comethod2 ?

SetRate comethod2 ?

GetRate comethod2 ?

SetVolume comethod2 ?

GetVolume comethod2 ?

WaitUntilDone comethod2 ?

SetSyncSpeakTimeout comethod2 ?

GetSyncSpeakTimeout comethod2 ?

SpeakCompleteEvent comethod1 ?

IsUISupported comethod5 ?

DisplayUI comethod6 ?

ISpVoice ENDS

;#########################################################################

;可变数据段

.data?

szbufferprev db 20 dup(?)

szbuffernow db 20 dup(?)

hWinMain DWORD ?

idTIMER DWORD ?

CommandLine DWORD ?

hInstance DWORD ?

hicon HICON ?

hmenu DWORD ?

hlib DWORD ?

timershowx DWORD ?

timershowy DWORD ?

showrect RECT <>

;常量数据段

.data

szClassName db "Timers_Class",0

szdateformat  db"yyyy年MM月dd日",0

sztimeformat db "hh点mm分ss秒",0

stnidstatus NOTIFYICONDATA <>

;======

isintpointalarmDWORD 1;0-表示整点不报时,1-整点报时

isshowtimer DWORD 1;0-表示不显示,1-显示

isintpoint  DWORD 0;0-表示不是整点,1-是整点

;======

sztooltip db "桌面报时工具",0

szabout db "桌面报时工具由WIN32汇编开发",0

szmscap db "错误",0

szmstext1 db "无法在桌面上显示!",0

szmstext2 db "无法得到全屏DC!",0

;======

szprevdate db 50 dup(?)

szprevtime db 50 dup(?)

sznowdate db 50 dup(?)

sznowtime db 50 dup(?)

szbegin db "桌面报时工具为您报时"

sztext db 100 dup(?)

;#########################################################################

;代码段

.code

_showtext  proto :DWORD

_ProcDlgMain proto :DWORD,:DWORD,:DWORD,:DWORD

_geterrno proto :DWORD,:DWORD

_speaktext proto :DWORD

_WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

_statusicon  proto :DWORD

_configload proto :DWORD

start:

;程序的入口

invoke GetModuleHandle, NULL

mov hInstance, eax

invoke GetCommandLine

mov CommandLine, eax

invoke _WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT

invoke ExitProcess,eax

;#########################################################################

;得到当前时间子函数

_getnow proc

invoke lstrcpy,addr szprevtime,addr sznowtime

invoke lstrcpy,addr szprevdate,addr sznowdate

invoke GetDateFormat,NULL,NULL,NULL,addr szdateformat,addrsznowdate,50

invokeGetTimeFormat,LOCALE_USER_DEFAULT,TIME_FORCE24HOURFORMAT,NULL,addrsztimeformat,addr sznowtime,50

invoke lstrcpy,addr sztext,addr sznowdate

invokelstrcat,addr sztext,addr sznowtime

invokeszLeft,addr szprevtime,addr szbufferprev,2

invokeszLeft,addr sznowtime,addr szbuffernow,2

invokelstrcmp,addr szbufferprev,addr szbuffernow

testeax,eax

je @f

mov isintpoint,1

@@:

ret

_getnow endp

;#########################################################################

;显示时间子函数

;参数说明:lpsztex:要显示的文本的起始地址

_showtext proc  uses  ebxlpsztext:DWORD

LOCAL@Desktopdc:HDC

LOCAL@dwtextcolor,@dwbkcolor

mov@dwtextcolor,00010000h

mov@dwbkcolor,0000FF00h

invokeGetWindowDC,NULL

cmpeax,0

jne@f

invokeMessageBox,NULL,offset szmstext2,offset szmscap,MB_ICONERROR

@@:

mov@Desktopdc,eax

invokelstrlen,lpsztext

movebx,eax

invokeSetBkColor,@Desktopdc,@dwbkcolor

invokeSetTextColor,@Desktopdc,@dwtextcolor

invokeTextOut,@Desktopdc,timershowx,timershowy,lpsztext,ebx

cmpeax,0

jne@f

invokeMessageBox,NULL,offset szmstext1,offset szmscap,MB_ICONERROR

@@:

invokeReleaseDC,NULL,HDC

ret

_showtext endp

;#########################################################################

_showtime proc

invoke _showtext,offset sztext

ret

_showtime endp

;#########################################################################

;语音朗读文本子函数

;参数说明: pszspeakansi:要朗读的文本起始地址

_speaktext proc uses edx ebx pszspeakansi:DWORD

.data

szspeaktext db 200dup(?),0

szerrtext db "错误号:"

szerrtextno db 20 dup(?),0

ppVoice  DWORD ?

CLSID_SpVoice GUID<96749377H,3391H,11D2H,<9EH,0E3H,00H,0C0H,4FH,79H,73H,96H>>

IID_ISpVoice GUID<6C44DF74H,72B9H,4992H,<0A1H,0ECH,0EFH,99H,6EH,04H,22H,0D4H>>

.code

invoke lstrlen,pszspeakansi

mov ebx,eax

invokeMultiByteToWideChar,CP_ACP,MB_PRECOMPOSED,pszspeakansi,-1,addrszspeaktext,ebx

invoke CoInitialize,NULL

;#######################################################################

;使用pVoice接口

invoke CoCreateInstance,addr CLSID_SpVoice,NULL,CLSCTX_ALL,addrIID_ISpVoice,addr ppVoice

.IF_FAILED

invoke _geterrno,eax,addr szerrtextno

invoke MessageBox,NULL,addr szerrtext,addr szmscap,MB_ICONERROR

jmp@f

.endif

mov eax,ppVoice

mov edx,[eax]

invoke (ISpVoice PTR[edx]).SetVoice,ppVoice,NULL

.IF_SUCCEEDED

mov eax,ppVoice

mov edx,[eax]

invoke(ISpVoice PTR[edx]).SetRate,ppVoice,3

.IF_FAILED

invoke _geterrno,eax,addr szerrtextno

invoke MessageBox,NULL,addr szerrtext,addr szmscap,MB_ICONERROR

.endif

mov eax,ppVoice

mov edx,[eax]

invoke(ISpVoice PTR[edx]).Speak,ppVoice,addr szspeaktext,0,NULL

.IF_FAILED

invoke _geterrno,eax,addr szerrtextno

invoke MessageBox,NULL,addr szerrtext,addr szmscap,MB_ICONERROR

.endif

.endif

mov eax,ppVoice

mov edx,[eax]

invoke (ISpVoice PTR[edx]).Release,ppVoice

@@:

call CoUninitialize

ret

_speaktext endp

;#########################################################################

;对话框消息处理函数

_ProcMain proc uses ebx hWnd,uMsg,wParam,lParam

LOCAL @stpos:POINT

.if uMsg==WM_TIMER

mov eax,wParam

.if eax==IDT_TIMER

call _getnow

.if isshowtimer==1

call_showtime

.endif

.if isintpointalarm==1 &&isintpoint==1

invoke _speaktext,addr szbegin

mov isintpoint,0

.endif

.endif

.elseif uMsg==WM_NOTIFYICONN

moveax,wParam

.if eax== IDR_MAINFRAME

mov eax,lParam

movzx eax,ax

.if eax== WM_RBUTTONUP

invoke GetCursorPos,addr @stpos

invokeTrackPopupMenu,hmenu,TPM_LEFTALIGN,@stpos.x,@stpos.y,NULL,hWnd,NULL

.endif

.endif

.elseif uMsg==WM_CLOCKALARM

invoke_speaktext,addr szbegin

.elseif uMsg==WM_COMMAND

moveax,wParam

movzxeax,ax

.ifeax==MENUID_EXIT

invoke InvalidateRect,NULL,NULL,NULL

invoke    UnInstallHook,hWnd

invoke KillTimer,hWnd,idTIMER

invoke _statusicon,NIM_DELETE

invoke DestroyWindow,hWnd

.elseif eax==MENUID_SYSTEMSET

invoke _configload,0

invoke ShowWindow,hWinMain,SW_SHOWNORMAL

.elseif eax==MENUID_ABOUT

invokeMessageBox,NULL,addr szabout,addr sztooltip,NULL

.elseif eax==MENUID_SPEAKTIMER

invoke_speaktext,addr szbegin

.elseifeax==IDC_CANCEL

invokeShowWindow,hWinMain,SW_HIDE

.elseif eax==IDC_OK

call _configsave

invokeShowWindow,hWinMain,SW_HIDE

.endif

.elseif uMsg==WM_DESTROY

invoke PostQuitMessage,NULL

.else

invoke DefDlgProc,hWnd,uMsg,wParam,lParam

ret

.endif

xor eax,eax

ret

_ProcMain endp

;#########################################################################   ;取得COM接口错误号函数,可以根据错误号在winerror.h中查到错误类型

_geterrno proc szerrhex:DWORD,pszerrtext:DWORD

push eax

invokedw2hex,szerrhex,pszerrtext

pop eax

ret

_geterrno endp

;#########################################################################   ; 状态栏图标操作

_statusicon  proc operation:DWORD

invoke Shell_NotifyIcon,operation,addr stnidstatus

ret

_statusiconendp

;#########################################################################   ;主窗口消息循环

_WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD

LOCAL @stwc:WNDCLASSEX

LOCAL @stmsg:MSG

LOCAL @CommandLine:DWORD

mov@stwc.cbSize,        sizeof WNDCLASSEX

mov@stwc.style,         CS_HREDRAW or CS_VREDRAW

mov@stwc.lpfnWndProc,   offset _ProcMain

mov@stwc.cbClsExtra,    NULL

mov@stwc.cbWndExtra,    DLGWINDOWEXTRA

push hInst

pop @stwc.hInstance

mov @stwc.hbrBackground,  COLOR_BTNFACE+1

mov @stwc.lpszMenuName,  NULL

mov @stwc.lpszClassName,  offset szClassName

invoke LoadIcon,hInst, IDR_MAINFRAME

mov hicon,eax

push hicon

pop @stwc.hIcon

push hicon

pop @stwc.hIconSm

invoke LoadCursor,NULL,IDC_ARROW

mov @stwc.hCursor,eax

invoke RegisterClassEx,addr @stwc

invoke CreateDialogParam,hInst,DIALOG_MAIN,NULL,NULL,NULL

mov   hWinMain,eax

invoke LoadMenu,hInst,IDR_MAINMENU

mov hmenu,eax

invoke GetSubMenu,hmenu,0

mov hmenu,eax

mov stnidstatus.cbSize,sizeof NOTIFYICONDATA

push hWinMain

pop stnidstatus.hwnd

mov stnidstatus.uID,IDR_MAINFRAME

push hicon

pop  stnidstatus.hIcon

mov stnidstatus.uFlags,NIF_ICON or NIF_TIP or NIF_MESSAGE

mov stnidstatus.uCallbackMessage,WM_NOTIFYICONN

invoke lstrcpy,addr stnidstatus.szTip,addr sztooltip

invoke ShowWindow,hWinMain,SW_HIDE

invoke UpdateWindow,hWinMain

invoke _configload,1

.while TRUE

invoke GetMessage,addr @stmsg,NULL,0,0

.BREAK .IF eax==0

invokeIsDialogMessage,hWinMain,addr @stmsg

.ifeax==FALSE

invoke TranslateMessage,addr @stmsg

invoke DispatchMessage,addr @stmsg

.endif

.endw

moveax,@stmsg.wParam

ret

_WinMain endp

;#########################################################################   ;加载配置

_configload proc isfirstrun:DWORD

.code

.if isfirstrun==1 ;第一次运行,需要读取文件和初始化

;初始化

invoke GetDateFormat,NULL,NULL,NULL,addr szdateformat,addrsznowdate,50

invokeGetTimeFormat,LOCALE_USER_DEFAULT,TIME_FORCE24HOURFORMAT,NULL,addrsztimeformat,addr sznowtime,50

invoke SetTimer,hWinMain,IDT_TIMER,1000,NULL

mov idTIMER,eax

invoke _statusicon,NIM_ADD;创建状态栏图标

invokeInstallHook,hWinMain,WM_CLOCKALARM;安装热键钩子

invoke GetSystemMetrics,SM_CXSCREEN

shreax,1

movtimershowx, eax

movtimershowy, 1

.endif

.if isintpointalarm==0

invokeCheckDlgButton,hWinMain,IDC_CHECKBS,BST_UNCHECKED

.else

invoke CheckDlgButton,hWinMain,IDC_CHECKBS,BST_CHECKED

.endif

.if isshowtimer==0

invokeCheckDlgButton,hWinMain,IDC_CHECKSHOWTIMER,BST_UNCHECKED

.else

invoke CheckDlgButton,hWinMain,IDC_CHECKSHOWTIMER,BST_CHECKED

.endif

ret

_configload endp

;#########################################################################   ;保存配置

_configsave proc

invoke IsDlgButtonChecked,hWinMain,IDC_CHECKBS

.if eax==BST_CHECKED

mov isintpointalarm,1

.else

mov isintpointalarm,0

.endif

invokeIsDlgButtonChecked,hWinMain,IDC_CHECKSHOWTIMER

.if eax==BST_CHECKED

mov isshowtimer,1

.else

mov isshowtimer,0

invoke InvalidateRect,NULL,NULL,NULL

.endif

ret

_configsave endp

;#########################################################################   end start

2、  DLL文件代码

.586

.model flat, stdcall

option casemap:none

;#########################################################################

include windows.inc

include user32.inc

include kernel32.inc

includelib user32.lib

includelib kernel32.lib

.data?

hHook DWORD ?

hMainWnd DWORD ?

hWmessage DWORD ?

.data

hInstance DWORD 0

sztooltip db "桌面报时工具",0

;#########################################################################

.code

;#########################################################################

;DLL入口

DllEntry prochInst:HINSTANCE,reason:DWORD,userreserved:DWORD

push hInst

pop hInstance

mov eax,TRUE

ret

DllEntry endp

;#########################################################################

;键盘消息处理函数

KeyProc proc uses ebx dwCode:DWORD,wParam:DWORD,lParam:DWORD

invokeCallNextHookEx,hHook,dwCode,wParam,lParam

.if dwCode == HC_ACTION&&wParam==VK_F12

mov ebx,1

shl ebx,30

test lParam,ebx

jne @f

invoke SendMessage,hMainWnd,hWmessage,0,0

@@:

.endif

xor eax,eax

ret

KeyProc endp

;#########################################################################

;安装HOOK函数

InstallHook proc hwnd:DWORD,dwmessage:DWORD

push hwnd

pop hMainWnd

push dwmessage

pop hWmessage

invokeSetWindowsHookEx,WH_KEYBOARD,addr KeyProc,hInstance,NULL

mov hHook,eax

ret

InstallHook endp

;#########################################################################

;卸载HOOK函数

UnInstallHook proc hwnd:DWORD

invoke UnhookWindowsHookEx,hHook

ret

UnInstallHook endp

;#########################################################################

end DllEntry

3、  DLL导出文件内容(声明DLL的外部函数)

KeyProc  proto :DWORD,:DWORD,:DWORD

InstallHook proto :DWORD,:DWORD

UnInstallHook proto :DWORD

用WIN汇编开发桌面报时工具相关推荐

  1. 前端开发桌面终极工具(FastStone Capture)推荐(转)

    前端开发桌面终极工具(FastStone Capture)推荐 Posted on : 26-03-2009 | By : 愚人码头 | In : 前端工具 2 FastStone Capture是一 ...

  2. 太强了,Python 开发桌面小工具,让代码替我们干重复的工作~

    作者 | Cherish 来源 | 杰哥的IT之旅 决定写这篇文章的初衷是来源于一位小伙伴的问题,关于"如何根据数据源用 Python 自动生成透视表",这个问题背后有个非常好的解 ...

  3. 太强了!Python 开发桌面小工具,让代码替我们干重复的工作!

    作者:Cherish 来源:https://www.jianshu.com/p/91128d442198 决定写这篇文章的初衷是来源于一位小伙伴的问题,关于"如何根据数据源用 Python ...

  4. Python 开发桌面小工具,让代码替我们干重复的工作!

    作者:Cherish 来源:https://www.jianshu.com/p/91128d442198 本文为读者投稿 决定写这篇文章的初衷是来源于一位小伙伴的问题,关于"如何根据数据源用 ...

  5. 太强了~Python 开发桌面小工具,让代码替我们干重复的工作

    决定写这篇文章的初衷是来源于一位小伙伴的问题,关于"如何根据数据源用 Python 自动生成透视表",这个问题背后有个非常好的解决思路,让代码替我们做重复的工作,从而减轻工作量,减 ...

  6. android AppWidgetProvider开发桌面小工具

    什么是桌面小工具  就是你写好代码后 双指缩放桌面屏幕(三星手机出现小组件,华为出现窗口小工具)点击之后会出现你继承AppWidgetProvider所编写的界面 效果: 代码: /** * Impl ...

  7. electron 托盘图标闪烁_从零到一,用 Electron 开发桌面效率工具

    Electron 已经不算新技术,最早是 github 从 Atom 编辑器衍生出来的框架.通过编写 Javascript, HTML, CSS 能快速编译出跨系统的桌面 app.Electron 的 ...

  8. 使用python快速开发桌面小工具

    参考链接 Welcome to Python.org Extending and Embedding the Python Interpreter - Python 3.7.3 documentati ...

  9. python开发工具管理系统_Python开发桌面软件文档及网址管理工具,强迫症的福音...

    原标题:Python开发桌面软件文档及网址管理工具,强迫症的福音 写在前面 这两天用python鼓捣开发了一个软件,分享给同事,觉得很实用,可以大大提高工作效率,想通过平台分享出来给大家 希望给爱好p ...

最新文章

  1. 高性能MySQL之架构与历史(1)
  2. mvvm模式和mvc的区别_mvvm 和 mvc 区别?
  3. (转)利用快速开发框架,快速搭建微信浏览博客园首页文章
  4. 深入理解 Flutter 的编译原理与优化
  5. python 垃圾回收机制
  6. 读书笔记 - 《我的美国之路》
  7. 大数据_Hbase-Filter 索引(优化)_根据column查询---Hbase工作笔记0020
  8. Adobe驳斥Flash过度耗电论 称HTML5更耗电
  9. Javascript对象数组排序
  10. Newton's Dark Secrets《牛顿探索》
  11. 名人名言摘选-李嘉诚
  12. 原生 android 手机,享受原汁原味的安卓:七款原生安卓系统手机推荐
  13. 【SpringSecurity】SpringSecurity2.7.x 的使用(03)
  14. linux双击打开二进制文件,linux下打开二进制文件
  15. ue4 unreal NDisplay插件 简易使用 三折幕 详细...
  16. 鸿蒙和iqoo系统谁强,鸿蒙系统发布会,小米11降500,iQOO、酷派、魅族、惠普发布新品...
  17. 计算机组装前需要的准备工作,手把手教你攒电脑:组装电脑全过程
  18. STM32固件库(标准外设库)入门学习 第四章OLED屏幕使用
  19. 赛宁网安-r3kapig联合战队冲击DEF CON CTF 2022总决赛
  20. 基于STM32智能小车->红外寻迹篇

热门文章

  1. 使用CUPS打印服务
  2. Java岗面试:mysql破解版百度云
  3. vscode上的git三部曲+git pull操作
  4. 加湿器-香薰机的设计方案(单片机程序+PCB)超声波震荡方式 原理图+PCB+源代码+详细设计说明
  5. Kindle资源-史上最全60GB的Kindle电子书资源网盘打包下载
  6. 金弘同创怎么样:拼多多获取奖励金的办法
  7. 我的世界Faithful Java_我的世界:原来我们都被骗了,这才Minecraft真实的样貌
  8. pycharm光标变成黑框,恢复成竖线
  9. VisionPro基本使用
  10. 首先dns服务器自动改变 萤石云,设备的DNS在哪里改 ?