📄 testsms.c
字号:
/*-------------------------------------------------------------
发送手机短信程序
江振健
http://www.my66.com
litth@yeah.net
---------------------------------------------------------------*/
#include <stdio.h>
#include <windows.h>
#include "testsmsres.h"
HWND hMain;
HINSTANCE hInst;
static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
/*-------------------------------------------------------------
函数名 :ShowMsg
功能 :在状窗显示字符串
参数 :msg--内容
返回值 :void
---------------------------------------------------------------*/
void ShowMsg(char *msg)
{
HWND hEdit=GetDlgItem(hMain,IDE_MSG);
int len=GetWindowTextLength(hEdit);
char *buf=malloc(len+strlen(msg)+100);
if(buf)
{
GetWindowText(hEdit,buf,len+10);
strcat(buf,msg);
SetWindowText(hEdit,buf);
SendMessage(hEdit,EM_LINESCROLL,0,
SendMessage(hEdit,EM_GETLINECOUNT,0,0));
free(buf);
}
}
/*-------------------------------------------------------------
函数名 :PduCode
功能 :生成短信的PDU编码字符串.
参数 :cnt --短信服务中心号码,sdt--接收号码(对方手机号),msg--短信内容.
返回值 :经PDU编码的字符串指针,如有错,其内容为空.
---------------------------------------------------------------*/
char *PduCode(char *cnt,char *sdt,char *msg)
{
static unsigned char pdu[1024]="",tmp1[1024],tmp2[20];
int i,k,len_cnt=strlen(cnt),len_sdt=strlen(sdt),len_msg=strlen(msg);
memset(pdu,0,sizeof(pdu));//把存放PDU编码的内存清零.
if(len_cnt>18||len_sdt>18||len_msg>100)return pdu;//判断参数是否有效.
strcpy(tmp1,cnt);//把服务中心号复制到tmp1
if(len_cnt%2==1){strcat(tmp1,"F");len_cnt++;}//若服务中心号长度为奇数则追加"F".
sprintf(pdu,"%02X",(len_cnt/2)+1);//服务中心号码长度.
if(!strncmp(cnt,"00",2))//判断服务中心号类型.
{
strcat(pdu,"81");
}
else
{//默认短信服务中心号前有"+",如+86130200500.
strcat(pdu,"91");
}
for(k=strlen(pdu),i=0;i<len_cnt;i++,k++)
{//每两个字节进行位置交换.
pdu[k]=i%2==0?tmp1[i+1]:tmp1[i-1];
}
//处理接收方手机号码.
sprintf(tmp2,"1100%02X81",len_sdt);
strcat(pdu,tmp2);
strcpy(tmp1,sdt);
if(len_sdt%2==1)
{//若接收方手机号长度为奇数则追加"F".
strcat(tmp1,"F");
len_sdt++;
}
for(i=0,k=strlen(pdu);i<len_sdt;i++,k++)
{//每两个字节进行位置交换.
pdu[k]=i%2==0?tmp1[i+1]:tmp1[i-1];
}
//处理被发送的短信的内容.
k=2*MultiByteToWideChar(CP_ACP,//转换成UNICODE.
MB_PRECOMPOSED,msg,len_msg,(unsigned short *)tmp1,sizeof(tmp1));
sprintf(tmp2,"0008FF%02X",k);
strcat(pdu,tmp2);
for(i=0;i<k;i++)
{//将短信内容每两个字节进行位置交换转成十六进制的字符串.
sprintf(tmp2,"%02X",i%2==0?tmp1[i+1]:tmp1[i-1]);
strcat(pdu,tmp2);
}
return pdu;
}
/*-------------------------------------------------------------
函数名 :ATCommand
功能 :发送AT命令到指定的串口
参数 :hComm--串口的句柄,cmd--AT命令
返回值 :发送AT命令后收到的字符指针
---------------------------------------------------------------*/
char *ATCommand(HANDLE hComm,char *cmd)
{
DWORD readwrite=0;
static char buf[1024];
ZeroMemory(buf,sizeof(buf));
WriteFile(hComm,cmd,strlen(cmd),&readwrite,NULL);
Sleep(1000);//等待调制解调器处理AT命令.
ReadFile(hComm,buf,sizeof(buf)-1,&readwrite,NULL);
ShowMsg(buf);
return buf;
}
/*-------------------------------------------------------------
函数名 :sms
功能 :发送短信
参数 :com--串口号, sendto--接收方手机号, msg--短信内容
返回值 :0
---------------------------------------------------------------*/
int sms(int com,char *sendto,char *msg)
{
char buf[1024],*p,*sms,*center=NULL;
HANDLE hComm;
DCB dcb;
int len,len_center;
COMMTIMEOUTS cto = { 20, 10, 10, 10, 10 };
sprintf(buf,"COM%d",com);
hComm=CreateFile(buf,
GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0);
if(hComm==INVALID_HANDLE_VALUE)
{
ShowMsg("通信串口打开错误.\r\n");
goto Quit;
}
GetCommState(hComm,&dcb);
dcb.BaudRate = CBR_9600; // 设置波特率为9600.
dcb.ByteSize = 8; // 字节为 8位.
dcb.Parity = NOPARITY; // Parity 为 None.
dcb.StopBits = ONESTOPBIT; // 1 个停止位.
if (!SetCommState(hComm, &dcb)) {// 设置通信端口状态.
ShowMsg("通信串口设置错误.");
goto Quit;
}
SetCommTimeouts(hComm,&cto);//设置超时时间.
if(!strstr(ATCommand(hComm,"AT\r"),"OK"))//判断手机是否支持AT命令.
{
ShowMsg("通信串口未连接手机或手机不支持AT命令.\r\n");
goto Quit;
}
//取短信服务中心号码.
for(p=ATCommand(hComm,"AT+CSCA?\r");*p!='\0';p++)
{//从引号间找出服务中心号,如:+CSCA: "8613010200500",145.
if(*p=='"' && center!=NULL)
{
*p='\0';break;
}
if(*p=='"' && center==NULL)
{
center=p+1;
}
}
if(center==NULL)
{
ShowMsg("找不到服务中心号码.\r\n");
goto Quit;
}
sms=PduCode(center,sendto,msg);//进行PDU编码.
if((len=strlen(sms)/2)<=0)
{
ShowMsg("PDU编码失败.\r\n");
goto Quit;
}
len_center=strlen(center);
if(len_center%2==1)
{
len_center++;
}
len-=(len_center/2)+2;//计算短信内容长度.
ATCommand(hComm,"AT+CMGF=0\r");//发送AT+CMGF=0<CR>.
sprintf(buf,"AT+CMGS=%d\r",len);
ATCommand(hComm,buf);//发送AT+CMGS=n<CR>.
ATCommand(hComm,sms);//发送经PDU编码的字符串.
ATCommand(hComm,"\32\r");//发送(CTRL+Z+<CR>)结束.
Quit:
CloseHandle(hComm);//关闭句柄.
return 0;
}
/*-------------------------------------------------------------
函数名 :InitializeIni
功能 :初始化变量
参数 :void
返回值 :void
---------------------------------------------------------------*/
void InitializeIni(void)
{
char INIFile[600];
char tmp[512];
GetCurrentDirectory(600,INIFile);
lstrcat(INIFile,"\\testsms.ini");
GetPrivateProfileString("Opt","COM","1",tmp,512,INIFile);
SetDlgItemText(hMain,IDE_COM,tmp);
GetPrivateProfileString("Opt","TO","13026889xyz",tmp,512,INIFile);
SetDlgItemText(hMain,IDE_SENDTO,tmp);
}
/*-------------------------------------------------------------
函数名 :SaveIni
功能 :保存Ini
参数 :void
返回值 :void
---------------------------------------------------------------*/
void SaveIni(void)
{
char INIFile[600];
char tmp[512];
GetCurrentDirectory(600,INIFile);
lstrcat(INIFile,"\\testsms.ini");
GetDlgItemText(hMain,IDE_COM,tmp,512);
WritePrivateProfileString("Opt","COM",tmp,INIFile);
GetDlgItemText(hMain,IDE_SENDTO,tmp,512);
WritePrivateProfileString("Opt","TO",tmp,INIFile);
}
/*-------------------------------------------------------------
函数名 :WinMain
功能 :主函数
参数 :
返回值 :
---------------------------------------------------------------*/
int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow)
{
hInst=hinst;
return DialogBox(hinst, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, (DLGPROC) DialogFunc);
}
/*-------------------------------------------------------------
函数名 :SendSMS
功能 :发送短信的线程
参数 :void
返回值 :void
---------------------------------------------------------------*/
void SendSMS(void)
{
char com[20];
char sendto[30];
char msg[200];
HWND hwnd;
hwnd=hMain;
EnableWindow(GetDlgItem(hwnd,IDOK),FALSE);
EnableWindow(GetDlgItem(hwnd,IDE_SENDTO),FALSE);
EnableWindow(GetDlgItem(hwnd,IDE_COM),FALSE);
EnableWindow(GetDlgItem(hwnd,IDE_TEXT),FALSE);
GetDlgItemText(hwnd,IDE_COM,com,2);
GetDlgItemText(hwnd,IDE_SENDTO,sendto,30);
GetDlgItemText(hwnd,IDE_TEXT,msg,54);
SetDlgItemText(hwnd,IDE_MSG,"");
if(strlen(msg)>0 && strlen(sendto)>0)
{
sms(atoi(com),sendto,msg);
}
else
{
ShowMsg("短信内容和和号码不能为空.\r\n");
}
EnableWindow(GetDlgItem(hwnd,IDOK),TRUE);
EnableWindow(GetDlgItem(hwnd,IDE_SENDTO),TRUE);
EnableWindow(GetDlgItem(hwnd,IDE_COM),TRUE);
EnableWindow(GetDlgItem(hwnd,IDE_TEXT),TRUE);
}
/*-------------------------------------------------------------
函数名 :HandleCommand
功能 :处理WM_COMMAND消息
参数 :hwnd,wParam,lParam
返回值 :void
---------------------------------------------------------------*/
void HandleCommand(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
char msg[200];
DWORD Id;
switch (LOWORD(wParam)) {
case IDOK:
CloseHandle(CreateThread(NULL,0,(LPTHREAD_START_ROUTINE )SendSMS,NULL,0,&Id));
return ;
case IDE_TEXT:
if(EN_CHANGE==HIWORD(wParam))
{ int len =GetWindowTextLength((HWND)lParam);
if(len<100)
{
wsprintf(msg,"字节数:%d",len);
SetDlgItemText(hwnd,IDC_STATUS,msg);
}
else
{
SetDlgItemText(hwnd,IDC_STATUS,"超过短信规定的字节数");
MessageBeep(0);
}
}
return ;
}
}
/*-------------------------------------------------------------
函数名 :DialogFunc
功能 :处理Window消息
参数 :hwndDlg,msg,wParam,lParam
返回值 :TRUE or FALSE
---------------------------------------------------------------*/
static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_INITDIALOG:
hMain=hwndDlg;
InitializeIni();
return TRUE;
case WM_COMMAND:
HandleCommand(hwndDlg,wParam,lParam);
return 1;
case WM_CLOSE:
SaveIni();
EndDialog(hwndDlg,0);
return TRUE;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -