本程序通过编程模拟自动柜员机(ATM)的工作。程序功能简单:1.查询余额;2.取款;3.退出系统。
程序中我使用了钩子,用以屏蔽某些消息。很可惜,经反复测试及上网查阅,发现无法在控制台程序中设置钩子,即钩过程没被执行。保留此钩子的相关代码,是为了与大家一同交流如何在控制台程序中实现与钩子一样的功能。
我把这个程序拿出来与大家共同交流,是因为我觉得编程能力的提高需要多多交流,要知道写出这个程序,我花了3天的时间!最后送大家一句话:永远不要承认自己没有天赋!
程序源码如下:
//hook.h
#define _WIN32_WINNT 0x500
#include <windows.h>
LRESULT CALLBACK LowLevelKeyboardProc(int nCode,WPARAM wParam,LPARAM lParam); //钩子过程函数声明
HHOOK g_hKeyboard=NULL;
HWND g_hWnd=NULL;
/*LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
if((0x31==wParam||0x32==wParam||0x33==wParam)&&s==NULL&&c==NULL)
{
SendMessage(g_hWnd,WH_KEYBOARD,0,0);
UnhookWindowsHookEx(g_hKeyboard);
return 0;
}
if(0x52==wParam&&c=='1')
{
SendMessage(g_hWnd,WH_KEYBOARD,0,0);
UnhookWindowsHookEx(g_hKeyboard);
return 0;
}
if((0x4e==wParam||0x59==wParam)&&c=='2')
{
SendMessage(g_hWnd,WH_KEYBOARD,0,0);
UnhookWindowsHookEx(g_hKeyboard);
return 0;
}
return 1;
}
void SetHook(HWND hwnd)
{
g_hWnd=hwnd;
g_hKeyboard=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandle("Hook"),0);
}*/
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
{
PKBDLLHOOKSTRUCT klhs = (PKBDLLHOOKSTRUCT)lParam;
if ((klhs->vkCode == '1'||klhs->vkCode == '2'||klhs->vkCode == '3')&&c!=NULL&&s!=NULL)
{
UnhookWindowsHookEx(g_hKeyboard);
return 0;
}
else if (c == '1'&&klhs->vkCode == 'r')
{
UnhookWindowsHookEx(g_hKeyboard);
return 0;
}
else if((klhs->vkCode == 'y'||klhs->vkCode == 'n')&&c=='2')
{
UnhookWindowsHookEx(g_hKeyboard);
return 0;
}
}
// return CallNextHookEx(g_hHook, nCode, wParam, lParam);
return 1;
}
void SetHook(HWND hwnd) //设置钩子
{
g_hWnd=hwnd;
g_hKeyboard=SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,NULL,GetCurrentThreadId());
}
//控制台句柄.h
HWND GetConsoleHwnd(void) //获取控制台程序窗口句柄
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles.
HWND hwndFound; // This is what is returned to the caller.
char pszWindowTitle[MY_BUFSIZE]; // Contains original
// WindowTitle.
::GetConsoleTitle(pszWindowTitle,MY_BUFSIZE);
hwndFound=::FindWindow(NULL,pszWindowTitle);
return(hwndFound);
}
//自动柜员机.cpp
#include<iostream.h>
#include <stdio.h>
#include<stdlib.h>
#include<memory.h>
char c=NULL,s=NULL; //全局变量,便于在hook.h文件中使用
#include"hook.h"
#include"控制台句柄.h"
#define TRUE 1
#define FALSE 0
void main()
{
unsigned int totalmonery,getmonery(0),i(0);//定义帐户余额和取款金额变量
char intstr[8]; //存储从数据文件moneydata.dat获取的整型字符窜
memset(intstr,0,8); //初始化数组全为0,0表示字符串结束符'/0'。#include<memory.h>
bool equalbool=TRUE;
bool YorS=TRUE;
FILE *moneydata; //文件操作,永久保存totalmonery
moneydata=fopen("moneydata.dat","rb");
fscanf(moneydata,"%s",intstr); //文件输入
totalmonery=(unsigned int )atoi(intstr); //保存在.dat或.txt文件中的数据都是字符窜,将一个整型
while(equalbool) //变量数据存储到文件中时,用itoa()将其转化为字符窜,再保存;否则乱码
{ //当从数据文件读取字符串时,用atoi()将获取的字符串转化
cout<<"/n欢迎使用自动柜员机!(肖志伟编写,谢谢共同分享!)/n"; //整型数据。
for(i=1;i<=60;i++)
{
cout<<"*";
}
cout<<"/n【1】查询余额"; //自动柜员机的菜单项
cout<<"/n【2】取款";
cout<<"/n【3】退出系统";
cout<<"/n请输入菜单序号:";
SetHook(GetConsoleHwnd()); //设置钩子,屏蔽某些消息。GetConsoleHwnd()用于获取控制台窗口句柄
cin>>c; //在此说明:经反复测试及上网查阅,发现无法在控制台程序
switch(c) //中设置钩子,即钩子过程没被执行。保留此钩子的相关代码,是为了与大家
{ //一同交流如何在控制台程序中实现与钩子一样的功能。
case '1':
cout<<"/n你的余额为:"<<totalmonery<<"元";
cout<<"/n请输入字母r以返回: ";
SetHook(GetConsoleHwnd());
cin>>s;
c=NULL;
system("cls"); //清屏函数。 #include<stdlib.h>
break;
case '2':
while(YorS)
{
cout<<"/n请输入的取款金额:";
cin>>getmonery;
if(getmonery>totalmonery)
{
cout<<"/n你的金额不足,请输入合适的金额数!";
cout<<"/n是否继续取款?输入y or n:";
SetHook(GetConsoleHwnd());
cin>>s;
if(s=='n'){ YorS=FALSE;}
s=NULL;
}
else
{
totalmonery-=getmonery;
cout<<"/n恭喜你取款成功!";
cout<<"/n是否继续取款?输入y or n: ";
cin>>s;
if(s=='n'){ YorS=FALSE;}
s=NULL;
}
}
system("cls");
break;
case '3':
equalbool=FALSE;
cout<<"/n谢谢合作,Goodby!/n";
break;
default:
break;
}//switch
}//while
moneydata=fopen("moneydata.dat","wb");
itoa(totalmonery,intstr,10); //itoa
fprintf(moneydata,"%s",intstr); //程序退出前保存帐户余额totalmonery
fclose(moneydata);
}