vc点滴2

启动一个进程的简单写法:
PROCESS_INFORMATION pi;
STARTUPINFO siStartInfo = {0};  //STARTUPINFO主要用于设置程序主窗口属性;置各项为0(默认值)
siStartInfo.cb = sizeof(siStartInfo);
BOOL isOK;
isOK = CreateProcess(NULL, _T("cmd.exe shutdown.exe"), NULL, NULL, FALSE,
   0, NULL, NULL, &siStartInfo, &pi);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);

 

LineDDA使用的简单例子:  //每一象素点调用一次回调函数myDDA
void CFgfgDlg::OnPaint()   //用在OnPaint或OnDraw内
{
    .....
 else
 {
  CPaintDC dc(this);
  CRect rt;
  GetClientRect(&rt);
  dc.SetTextAlign(TA_CENTER|TA_BOTTOM);
  ::LineDDA(rt.right, 0, rt.right/2, rt.bottom/2,
   (LINEDDAPROC)myDDA, (LPARAM)(LPVOID)&dc);
  ::LineDDA(rt.right/2, rt.bottom/2, rt.right-60, rt.bottom-10,
   (LINEDDAPROC)myDDA, (LPARAM)(LPVOID)&dc);

  CDialog::OnPaint();
 }
}
//static CALLBACK myDDA(int x, int y, LPARAM dc);  声明为静态成员函数
void CALLBACK CFgfgDlg::myDDA(int x, int y, LPARAM dc) 
//x,y为象素点坐标,dc为LineDDA最后一参数
{
 //static char str[] = "hi, clx";
 //((CDC*)dc)->TextOut(x, y, str, sizeof(str)-1);
 ((CDC*)dc)->Ellipse(x-10, y-10, x+10, y+10);
 for (long i=0; i<950000; i++);  //延迟一下
}


CTime使用一例:
 CTime tOld = CTime::GetCurrentTime();
 Sleep(10000);
 CTime tCur = CTime::GetCurrentTime();
 CTimeSpan t = tCur - tOld;  //时间间隔
 long s = t.GetTotalSeconds();  //转为秒
 CString str;
 str.Format("%ld", s);
 MessageBox(str);

 

CreatePipe创建一个管道,这个管道有输入端和输出端,同时也创建了管道使用的缓冲区
一个例子:
void CTestPipeDlg::OnButton1()
{
 /*
  BOOL CreatePipe(
  PHANDLE hReadPipe,                       // read handle
  PHANDLE hWritePipe,                      // write handle
  LPSECURITY_ATTRIBUTES lpPipeAttributes,  // security attributes
  DWORD nSize                              // pipe size

  CreateProcess(
LPCWSTR lpszImageName,
LPCWSTR lpszCmdLine,
LPSECURITY_ATTRIBUTES lpsaProcess,
LPSECURITY_ATTRIBUTES lpsaThread,
BOOL fInheritHandles,
DWORD fdwCreate,
LPVOID lpvEnvironment,
LPWSTR lpszCurDir,
LPSTARTUPINFOW lpsiStartInfo,
LPPROCESS_INFORMATION lppiProcInfo);
);  */

 SECURITY_ATTRIBUTES sa;
 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
 sa.bInheritHandle = TRUE;
 sa.lpSecurityDescriptor = NULL;
 HANDLE hRead, hWrite;

 if (!CreatePipe(&hRead, &hWrite, &sa, 0))
 {
  MessageBox(_T("创建管道失败"));
  return;
 }
 //这时当前进程拥有管道的输入和输出端

 //再建一个进程,让它的输出连到这个管道,这样的话这个管道就有两个输入一个输出了,不合理,
 //因此还要关闭当前进程所拥有的输入端
 PROCESS_INFORMATION pi;
 STARTUPINFO si = {0};
 si.cb = sizeof(STARTUPINFOW);
 si.hStdError = hWrite;    //这个进程的所有输出信息将自动写到管道缓冲区中
 si.hStdOutput = hWrite;
 si.wShowWindow = SW_HIDE;  //隐藏
 si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
 if (!CreateProcess(NULL, _T("cmd.exe help/?"), NULL, NULL, TRUE,
   0, NULL, NULL, &si, &pi))
 {
  MessageBox(_T("创建进程失败"));
  return;
 }
 CloseHandle(hWrite);

/*BOOL ReadFile(
  HANDLE hFile,                // handle to file
  LPVOID lpBuffer,             // data buffer
  DWORD nNumberOfBytesToRead,  // number of bytes to read
  LPDWORD lpNumberOfBytesRead, // number of bytes read
  LPOVERLAPPED lpOverlapped    // overlapped buffer
);
*/
 //读取管道缓冲区里面的内容(cmd dir/?)
 char readBuf[4096] = {0};
 DWORD dwCount;
 while (TRUE)
 {
  if (!ReadFile(hRead, readBuf, 4095, &dwCount, NULL))
  {
   break;
  }
  m_strEdit += readBuf;  //m_strEdit为成员变量(CString)
  m_strEdit += "/r/n";
  UpdateData(FALSE);
  Sleep(200);
 } 
}


关于__stdcall和__cdecl调用方式
以下是别人写的一段话:
_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在

退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数


C调用约定(即用__cdecl关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送

参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。另外,在

函数名修饰约定方面也有所不同。
_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行

文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加

上下划线前缀。是MFC缺省调用约定。

 

宏APIENTRY,WINAPI和CALLBACK指的是同一东西:__stdcall(回调函数或api都是用这种调用方式)

 

kbhit用来检测键盘是否有按键,有则返回-1,没有则返回0. 如果想知道按下了什么键,应该用getch()来获

取(键值已经输入缓冲区,getch从缓冲区中取得而非再从键盘输入). 你给出的程序应该是一个不会正常退

出的死循环吧(不管按什么键),因为, while (!kbhit()) m = getch(); getch()会中断等待你从键盘输入

,这个输入不会被kbhit检测到(此时中断处理中),而待中断处理完后(输入一个字符后)再转到kbhit,而此

时又没有输入马上再次转到getch(). 我给一个我见过的用法:
#include <stdio.h>

void main()
{
char m;
int i = 0;
while (1)
{
while (!kbhit())
{
i++;
if (i == 8)
i = 0;
sound(i);
}
m = getch();
printf("m == %c/n", m);
if (m == 's')
{
nosound();
break;
}
}
getch();
}

 

两个进程间用发送消息的方式通信,而且希望带上个字符串发送过去,应该考虑发送WM_COPYDATA消息.下面

是一个例子:
//发送端
  char fileName[100];
  memset(fileName, 0, 100);
  GetModuleFileName(NULL, fileName, 100);
  
  COPYDATASTRUCT cpd;
  cpd.dwData = 0;
         cpd.cbData = strlen(fileName);
         cpd.lpData = (void*)fileName;

  CString strTitle = "";
  strTitle = ReadIniFile("ServerTitle"); //自定义,取窗口标题
  HWND hServer = FindWindow(NULL, strTitle);
  if (hServer)
  { //发送(不用PostMessage)
   ::SendMessage(hServer, WM_COPYDATA, 0, (LPARAM)&cpd);
  }
 
//接收端,给出WM_COPYDATA映射宏 ON_WM_COPYDATA()
//处理函数声明 afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);
//在处理函数里面写:
 CString strName("");
 strName = (LPCSTR)(pCopyDataStruct->lpData);
 strName = strName.Left(strName.Find(".exe", 0));
 strName += ".exe";
 MessageBox(strName);

 return CWnd::OnCopyData(pWnd, pCopyDataStruct);
//例子结束

如果是同一个进程内发(send or post)消息来带去一个字符串,可以发送一个自定义的消息,用wParam或

lParam来保存字符串的地址(32位,强制转为wParam或lParam),在处理这个消息时只需把wParam或lParam转

为char*就可以了. 操作系统(可能是User32.dll)应该在发送消息时为这个字符串再分配了一个空间来存

放,并记录下这个空间的地址,在调用消息处理函数时把这个地址传给了相应的wParam或lParam.
但对于两个进程间以发送自定义消息的方式来通信的情况,带字符串的目的没有达到,我的接收端得到的是

空值.我估计这种方法不行. 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值