⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 9929.txt

📁 关于编程技术技巧的文章
💻 TXT
📖 第 1 页 / 共 4 页
字号:
        ); 
  此方法可以以同步或异步方式操作
  例程:
  COMMTIMEOUTS to;
  ...
  DWORD ReadTherad(LPDWORD lpdwParam)
  {
  BYTE binbuff[100];
  DWORD nBytesRead,dwEvent,dwError;
  COMSTAT cs;
  SetCommMask(hComm,EV_RXHAR);
  while(bReading)
  {
	if(WaitCommEvent(hComm,&dwEvent,NULL))
	{
	  ClearCommError(hComm,&dwError,&cs);
	  if((dwEvent&EV_RXCHAR)&&cs.cbInQue)
	  {
	     if(!ReadFile(hComm,inbuff,cs.cbInQue,&nBytesRead,NULL)
		locProcessCommError(GetLastError());
	  }
 	  else
	  {
	    if(nByteRead)
		locProcessBytes(inbuff,nBytesRead);
	  }
	else
	  locProcessCommError(GetLastError());
  }
  PurgeComm(hComm,PURGE_RXCLEAR);
  return 0L;
}
  NOTE: SetCommMask(hComm,0)可使WaitCommEvent()中止.

  可使用GetCommmodemStatus()方法,例程:
  if(cp.dwProvCapabilities&PCF_RTSCTS)
  {
     SetCommMask(hComm,EV_CTS);
     WaitCommEvent(hComm,&dwMask,NULL);
     if(dwMask&EV_CTS)
     {
 	GetCommModemStatus(hComm,&dwStatus)
	if(dwStatus&MS_CTS_ON)  /* CTS stransition OFF-ON */
        else                    /* CTS stransition ON-OFF */
     }
   }
   MS_CTS_ON	CTS为ON
   MS_DSR_ON	DSR为ON
   MS_RING_ON	RING为ON
   MS_ELSD_ON	RLSD为ON

14.错误
  当发生错误时应用方法ClearCommError(hComm,&dwErrorMask,&constat)
  得到错误掩码。
  CE_BREAK	中止条件
  CE_FRAME	帧错误
  CW_IOE	一般I/O错误,常伴有更为详细的错误标志
  CE_MODE	不支持请求的模式
  CE_OVERRUN	缓冲区超限下一个字符将丢失
  CE_RXOVER	接收缓冲区超限
  CE_RXPARITY	奇偶校验错误
  CE_TXFULL	发送缓冲区满  
  CE_DNS	没有选择并行设备
  CE_PTO	并行设备发生超时 
  CE_OOP	并行设备缺纸

15.控制命令
  EscapeCommFunction()可将硬件信号置ON或OFF,模拟XON或XOFF
  BOOL EscapeCommFunction(
	HANDLE hFile,  // handle to communications device 
 	DWORD dwFunc   // extended function to perform 
  	); 
  dwFunc的有效值(可用‘|’同时使用多个值)
  CLRDTR	DTR置OFF
  CLRRTS	RTS置OFF
  SETDTR	STR置ON
  SETRTS	TRS置ON
  SETXOFF	模拟XOFF字符的接收
  SETXON	模拟XON字符的接收
  SETBREAK	在发送中产生一个中止
  CLRBREAK	在发送中清除中止

****************************************************************

                    在Delphi中不使用VCL库建立窗口 

                              长沙 陈锐

  Borland的Delphi语言中提供了类似于VB中ActiveX的VCL控件库,利用
它建立程序界面是十分方便的,但是这也带来了一个问题,就是即使建立
一个非常简单的窗口,Delphi也会将所有的控件编译进去,使得程序十分
庞大(通过常规方式建立一个仅包含一个窗口,不响应任何消息的程序的
尺寸大概就有至少200K字节以上)。
  这里,我向大家介绍一个不使用VCL库建立窗口的方法。首先打开一个
文本编辑器(例如NotePad),然后在其中输入以下的程序代码:
  program Project2;
  uses
   Windows;
  const
   AppName = ‘Windows’;
   WM_DESTROY = 2;
   WM_LBUTTONUP = 514;
  {$R *.RES}
  //窗口处理函数
  function WindowProc(Window:Hwnd;Amessage,wParam,
   lParam:LongInt):LongInt;stdcall;export;
  begin
   WindowProc:=0;
   case AMessage of
   WM_DESTROY:
   begin
   PostQuitmessage(0);
   Exit;
   end;
   WM_LBUTTONUP:
   begin
   PostQuitmessage(0);
   Exit;
   end;
   end;
   WindowProc := DefWindowProc(Window,AMessage,wParam,lParam);
  end;
  
  //注册窗口函数
  function WinRegister:Boolean;
  var
   WindowClass:TWndClass;
  begin
  WindowClass.style:=cs_hredraw or cs_vRedraw or cs_NoClose;
   WindowClass.lpfnWndProc := @WindowProc;
   WindowClass.cbClsExtra := 0;
   WindowClass.cbWndExtra := 0;
   WindowClass.hInstance := Hinstance;
   WindowClass.hIcon := LoadIcon(0,idi_Application);
   WindowClass.hCursor := LoadCursor(0,idc_Arrow);
  WindowClass.hbrBackground:=HBrush(COLOR_BTNFACE);
   WindowClass.lpszMenuName := nil;
   WindowClass.lpszClassName := AppName;
  
   Result:=RegisterClass(WindowClass)<>0;
  end;
  
  //建立工具栏窗口函数
  function WinCreate:HWnd;
  var
   hWindow:Hwnd;
   pcharTemp:PChar;
  begin
   hWindow:=CreateWindowEx(WS_EX_RTLREADING or WS_EX_TOOLWINDOW,
   AppName,‘Samples Window’,ws_OverlappedWindow,
   cw_UseDefault,cw_UseDefault,cw_UseDefault,cw_UseDefault,0,0,
   Hinstance,nil);
   if hWindow<>0 then
   begin
   pcharTemp:=‘Samples’;
   ShowWindow(hWindow,cmdShow);
   TextOut(GetWindowDC(hWindow),10,50,pcharTemp,7);
   UpdateWindow(hWindow);
   end;
  
   Result:=hWindow;
  end;
  
  var
   AMessage:TMsg;
   hWindow:HWnd;
  begin //主程序部分
   if not WinRegister then
   begin
   MessageBox(0,‘窗口注册失败’,nil,mb_ok);
   Exit;
   end;
   hWindow:=WinCreate;
   if hWindow=0 then
   begin
   MessageBox(0,‘建立窗口失败’,nil,mb_ok);
   Exit;
   end;
   While GetMessage(AMessage,0,0,0)do
   begin
   TranslateMessage(AMessage);
   DispatchMessage(AMessage);
   end;
   Halt(AMessage.wParam);
  end.
  将上面的内容以 Project2.dpr 为文件名保存到Delphi的Bin目录中,
然后使用Delphi中的DCC32来编译工程文件,具体的使用方法是:
DCC32 Project2.dpr 。在编译过程中可能有一些警告(Warning)消息,
不要理会。编译完成后,在Bin目录下会产生一个Project2.exe的文件,
查看一下,这个文件是不是“缩水”了很多呢?在我的机器上编译出来的
程序只有17K左右,这同使用C++编译的程序大小几乎没有什么两样。
  分析上面的程序,使用C++编写过Windows下程序的读者可能会觉
得十分的熟悉,的确,同C++编写一样。在Delphi中不使用VCL编写窗
口界面也需要三个函数:窗口建立函数、窗口注册函数和窗口消息处理
函数。在上面的程序中,函数WinCreate是窗口建立函数,这个函数通过
CreateWindowsEx函数建立一个工具栏窗口,窗口建立成功后显示窗口并
在窗口中10,50的位置输出“Samples”。WindowProc函数是窗口消息处
理函数,这个函数只处理两个消息:WM_DESTROY和WM_LBUTTONUP。在得
到这两个消息后退出。WinRegister是窗口注册函数,这个函数注册
WinCreate建立的窗口并禁止窗口系统菜单的“关闭”项,同时将W
indowProc定义为窗口消息处理函数。
  对于使用Pascal语言,对C++不熟悉的朋友来说,只要根据自己的
需要对上面的程序稍微做一些修改,就可以编写同C++编写出来的一样
“苗条”的程序了。
  以上程序在Borland Delphi4.0,Win98下编译通过。 

****************************************************************

                            “磁性”窗口 

                              上海 汪箴

  Winamp的用户都知道,Winamp的播放列表或均衡器在被移动的时候,仿
佛会受到一股磁力,每当靠近主窗口时就一下子被“吸附”过去,自动沿边
对齐。我想让我的Winamp插件也具备这种奇妙特性,于是琢磨出了一种“磁
化”窗口的方法。该法适用于Delphi的各个版本。为了演示这种技术,请随
我来制作一个会被Winamp“吸引”的样板程序。
  先新建一应用程序项目,把主窗口Form1适当改小些,并将BorderStyle
设为bsNone。放一个按钮元件,双击它并在OnClick事件中写“Close;”。
待会儿就按它来结束程序。现在切换到代码编辑区,定义几个全局变量。
  var
   Form1: TForm1; //“磁性”窗口
   LastX, LastY: Integer; //记录前一次的坐标
   WinampRect:TRect; //保存Winamp窗口的矩形区域
   hwnd_Winamp:HWND; //Winamp窗口的控制句柄
  接着编写Form1的OnMouseDown和OnMouseMove事件。
  procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
   Shift: TShiftState; X, Y: Integer);
  const
   ClassName=‘Winamp v1.x’; //Winamp主窗口的类名
   //如果改成ClassName=‘TAppBuilder’,你就会发现连Delphi也有引力啦!
  begin
  //记录当前坐标
  LastX := X;
  LastY := Y;
  //查找Winamp
  hwnd_Winamp := FindWindow(ClassName,nil);
  if hwnd_Winamp>0 then //找到的话,记录其窗口区域
  GetWindowRect(hwnd_Winamp, WinampRect);
  end;
  procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
   Y: Integer);
  var
   nLeft,nTop:integer; //记录新位置的临时变量
  begin
  //检查鼠标左键是否按下
   if HiWord(GetAsyncKeyState(VK_LBUTTON)) > 0 then
   begin
   //计算新坐标
   nleft := Left + X - LastX;
   nTop := Top + Y - LastY;
   //如果找到Winamp,就修正以上坐标,产生“磁化”效果
   if hwnd_Winamp>0 then
   Magnetize(nleft,ntop);
   //重设窗口位置
   SetBounds(nLeft,nTop,width,height);
   end;
  end;
  别急着,看Magnetize()过程,先来了解一下修正坐标的原理。根据对
Winamp实现效果的观察,我斗胆给所谓“磁化”下一个简单的定义,就是
“在原窗口与目标窗口接近到某种预定程度,通过修正原窗口的坐标,使两
窗口处于同一平面且具有公共边的过程”。依此定义,我设计了以下的“磁
化”步骤。第一步,判断目标窗口(即Winamp)和我们的Form1在水平及垂直
方向上的投影线是否重叠。“某方向投影线有重叠”是“需要进行坐标修正”
的必要非充分条件。判断依据是两投影线段最右与最左边界的差减去它们宽
度和的值的正负。第二步,判断两窗口对应边界是否靠得足够近了。肯定的
话就让它们合拢。
  好了,下面便是“神秘”的Magnetize过程了……
  procedure TForm1.Magnetize(var nl,nt:integer);
   //内嵌两个比大小的函数
   function Min(a,b:integer):integer;
   begin
   if a>b then result:=b else result:=a;
   end;
   function Max(a,b:integer):integer;
   begin
   if a    end;
  var
   H_Overlapped,V_Overlapped:boolean; //记录投影线是否重叠
   tw,ww,wh:integer; //临时变量
  const
   MagneticForce:integer=50; //“磁力”的大小。
   //准确的说,就是控制窗口边缘至多相距多少像素时需要修正坐标
   //为了演示,这里用一个比较夸张的数字——50。
   //一般可以用20左右,那样比较接近Winamp的效果
  begin
  //判断水平方向是否有重叠投影
  ww := WinampRect.Right-WinampRect.Left;
  tw := Max(WinampRect.Right,nl+Width)-Min(WinampRect.Left,nl);
  H_Overlapped := tw<=(Width+ww);
  //再判断垂直方向
  wh := WinampRect.Bottom-WinampRect.Top;
  tw := Max(WinampRect.Bottom,nt+Height)-Min(WinampRect.Top,nt);
  V_Overlapped := tw<=(Height+wh);
  //足够接近的话就调整坐标
  if H_Overlapped then
   begin
   if Abs(WinampRect.Bottom-nt)    
      else if Abs(nt+Height-WinampRect.Top)    
    end;
  if V_Overlapped then
   begin
   if Abs(WinampRect.Right-nl)    
      else if Abs(nl+Width-WinampRect.Left)    
    end;
  end;
  怎么样?运行后效果不错吧!
  我设计的一个卡拉OK插件就应用了这种技术,你可以到
http://www.lotof.com/lyrics去下载它作为参考。

****************************************************************

                 用VB实现“ICQ”式的启动欢迎画面 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -