VC常用代碼

===========================================================
//注意事項
//先執行OnInitDialog()函數,然後執行構造函數!
//98下沒有新宋體
//XP下窗口高度加8
===========================================================
………1,滾動條處理方法
//1,設置範圍
m_spscroll.SetScrollRange(0,200);
SCROLLINFO si;
si.cbSize=sizeof(SCROLLINFO);
si.nPage=100;
si.fMask=SIF_PAGE;//設置頁寬
m_spscroll.SetScrollInfo(&si);
//2,處理消息,垂直滾動條加WM_VSCROLL消息,水平加WM_HSCROLL消息
void CPrintView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if(pScrollBar->GetDlgCtrlID()==IDC_SCROLLBAR1)
{
int nCurrentPos=pScrollBar->GetScrollPos();
SCROLLINFO si;
si.fMask=SIF_PAGE;//取得頁寬
pScrollBar->GetScrollInfo(&si);
switch(nSBCode)
{
case SB_THUMBTRACK://移動滑塊
case SB_THUMBPOSITION:
pScrollBar->SetScrollPos(nPos); //設置頁寬後滾動條的pos會以max/nPage倍數減少,所以在使用時注意把pos值*(max/nPage)能得到原值
break;
case SB_LINEUP://點向上小三角
pScrollBar->SetScrollPos(nCurrentPos-1);
break;
case SB_LINEDOWN://點向下小三角
pScrollBar->SetScrollPos(nCurrentPos+1);
break;
case SB_PAGEUP://向上一頁
pScrollBar->SetScrollPos(nCurrentPos-si.nPage);
break;
case SB_PAGEDOWN://向下一頁
pScrollBar->SetScrollPos(nCurrentPos+si.nPage);
break;
}
}
CDialog::OnVScroll(nSBCode, nPos, pScrollBar); {}

………2,鎖定鼠標
bool pOld;
CRect rt;
SetForegroundWindow();
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,true,&pOld,SPIF_UpdateINIFILE);
GetWindowRect(rt);
ClipCursor(rt);
//加到 LRESULT CLockDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 會有意外的效果

………3,在列表字符前插入一個負數字符以修改亂碼
int index=m_list.GetSelectionMark();//在列表字符前插入一個負數字符以修改亂碼
CString cs;
cs=m_list.GetItemText(index,0);
char insert_char=-87;
cs.Insert(0,insert_char);
m_list.SetItemText(index,0,cs);

………4,在列表中添加項目最大隻能顯示259個字符(不含'/0')
int char_length=cs.GetLength();//cs,ct爲CString類對象,是要發到列表框的文本但是可能大於259字節
while(char_length>259)//如果大於259字節
{
ct=cs.Left(259);
m_list.InsertItem(0,ct);//在列表中添加項目最大隻能顯示259個字符(不含'/0')
cs=cs.Right(char_length-259);
char_length=cs.GetLength();
}
m_list.InsertItem(0,cs);//在列表中添加項目最大隻能顯示259個字符(不含'/0')

………5,設置NT窗口的透明度
OSVERSIONINFO osv;
osv.dwOSVersionInfoSize=sizeof OSVERSIONINFO;
GetVersionEx(&osv);//取得版本信息
if(osv.dwPlatformId==VER_PLATFORM_WIN32_NT)//VER_PLATFORM_WIN32_WINDOWS 98 Me用這個宏
{
//加入WS_EX_LAYERED擴展屬性
SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,
GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);//如果多次調用下面這個函數設置,這個函數只在一個位置調用一次就行了
HINSTANCE hInst = LoadLibrary("User32.DLL");
if(hInst)
{
typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
MYFUNC fun = NULL;
//取得SetLayeredWindowAttributes函數指針
fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
if(fun)fun(this->GetSafeHwnd(),0, 200,//0 ~ 2552);
FreeLibrary(hInst);
}
}

………6,字體對話框的初始化
LOGFONT lf;
lf.lfHeight=-35;
lf.lfCharSet=134;
lf.lfWeight=400;
lf.lfOutPrecision=3;
lf.lfClipPrecision=2;
lf.lfQuality=1;
lf.lfPitchAndFamily=2;
strcpy(lf.lfFaceName,"宋體");//以上初始化爲宋體26號字
CFontDialog cf(&lf);//字體
cf.m_cf.rgbColors=textcolor;//顏色

………7,移動沒有標題的窗口
//1定義:
CPoint just_point;
//2
void CClockfortecherDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
just_point=point;
CDialog::OnLButtonDown(nFlags, point);
}
//3
void CClockfortecherDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
WINDOWPLACEMENT wi;
GetWindowPlacement(&wi);
if(nFlags==MK_LBUTTON)
SetWindowPos(&wndTop,wi.rcNormalPosition.left+(point.x-just_point.x), wi.rcNormalPosition.top+(point.y-just_point.y),
0,0,SWP_NOSIZE);
CDialog::OnMouseMove(nFlags, point);
}

………8,線程與信號量
//1,定義信號量句柄
HANDLE event;
//2,創建信號量
event=CreateEvent(NULL, TRUE, FALSE, NULL);
//3,創建線程:
//1)定義線程函數,格式必須如下,其中lParam爲AfxBeginThread的第二個參數值,可強制轉化成所需類型
UINT WorkThreadProc(LPVOID lParam)//必須是 UINT XXX..XXX(LPVOID lParam)
{
//代碼示例WaitForSingleObject:
while(1)
{
//注意,如果線程間要求同步或互斥的時候,要在每一層循環體中加入WaitForSingleObject
WaitForSingleObject((HANDLE)lParam, INFINITE);
//WaitForSingleObject的使用方法:第一個爲信號量HANDLE,是CreateEvent的返回值,第二個參數爲等待的毫秒數(1/1000秒)
//第二個參數爲INFINITE時則一直等待,直到調用SetEvent()設置信號量時函數返回;爲數值(如1000)則函數在1秒後返回
//(即使你沒調用SetEvent()設置信號量)
AfxMessageBox("fuck");//不能用MessageBox()因爲這不是在類中了...
ResetEvent((HANDLE)lParam);
//重置信號量,以使WaitForSingleObject函數可以繼續等待,否則(如果你已經調用過了SetEvent()設置了信號量)
//WaitForSingleObject函數將會立刻返回
}
}
//2)用AfxBeginThread創建一個WorkThreadProc的線程
AfxBeginThread(WorkThreadProc,event);
//4,在主程序需要的地方調用SetEvent()設置信號量啓動線程
SetEvent(event);//或者用WaitForMultipleObjects函數
static UINT __stdcall WorkThreadProc(void* pThis);
//如果lParam參數爲一個對話框的指針,想調用這個對話框的變量或函數那麼就得這樣定義線程函數,還要將WorkThreadProc改成//Wait_forDlg::WorkThreadProc,這樣WorkThreadProc就成爲CWait_forDlg類的函數,在這個線程裏就可以調用該類的變量了,注意得用_beginthreadex函數創建線程
UINT CWait_forDlg::WorkThreadProc(void * lParam)
{
CWait_forDlg *pThis=(CWait_forDlg *)lParam;
HANDLE hObjects[2];
hObjects[0] = pThis->event1;
hObjects[1]= pThis->event2;
while(1)
{
DWORD dwWait = WaitForMultipleObjects(2,hObjects,TRUE,INFINITE);
//第一個參數爲信號量個數2,第二個爲指針,第三個如果爲TRUE函數要等待兩個信號量都被SetEvent才返回,返回值爲最後一個
//SetEvent的WAIT_OBJECT_0+i;而爲FALSE則只要有一個被SetEvent就返回,返回值爲 WAIT_OBJECT_0+i 即信號量在數組中的位置
//+WAIT_OBJECT_0 */
if (dwWait == WAIT_OBJECT_0) AfxMessageBox("fcuk 1 ");
//開始ping
if (dwWait == WAIT_OBJECT_0 + 1)
AfxMessageBox("fcuk 2");
ResetEvent(hObjects[1]);
ResetEvent(hObjects[0]);
}
}

#include <process.h> /* 調用_beginthread, _endthread 得包涵這個頭文件*/
_beginthreadex(NULL,
0,
WorkThreadProc,
(void*) this,
0,
0);
//第三種創建線程的方法:
HANDLE thread;
DWORD threadrid; //線程ID
DWORD WINAPI sniff(LPVOID no){} //線程函數這樣定義
thread=CreateThread(NULL, //安全屬性
0, //棧大小
sniff, //要創建的線程名
NULL, //參數(一般爲調用線程的指針)
0, //創建標誌
&threadrid); //線程ID
CloseHandle(thread);
………9,操作數據庫ODBC
//在stdafx.h中加入 #include <afxdb.h>
//1,用類嚮導,建立基於CRecordset或CDaoRecordset的新子類,並選擇數據源m_setComplete
//2,添加
if ( ! m_setComplete . IsOpen () ) // if the recordset isn't already open..
m_setComplete . Open (); // open it
m_setComplete . AddNew (); // begin the add
m_setComplete . m_strCallsign = strCallsign; // change the recordset members
m_setComplete . m_strFrequency = strFrequency;
m_setComplete . m_strCity = strCity;
m_setComplete . m_strState = strState;
m_setComplete . m_strInput = strInput;
m_setComplete . Update (); // complete the add by doing an update
m_setComplete . Close (); // close the recordset
//3,修改
if ( ! m_setComplete . IsOpen () ) // if the recordset isn't already open..
m_setComplete . Open (); // open it
m_setComplete . Edit (); // begin the edit
m_setComplete . m_strCallsign = strCallsign; // change the recordset members
m_setComplete . m_strFrequency = strFrequency;
m_setComplete . m_strCity = strCity;
m_setComplete . m_strState = strState;
m_setComplete . m_strInput = strInput;
m_setComplete . Update (); // complete the add by doing an update
m_setComplete . Close (); // close the recordset
//4,刪除
/* 1, DAO 數據庫,不是ODBC
if (!m_setComplete . IsOpen () )
m_setComplete . Open ();
// cycle through the selected listbox elements.
strRecordIdQuery =CString ("[ID]=")+CString(m_lcRepeaterList.GetItemText(nItemIndex,0)); // put the ID into the query string
MessageBox(strRecordIdQuery);
if ( m_setComplete.FindFirst(strRecordIdQuery)) { // looking for this ID in the database, ID is a unique 'autonumber'
m_setComplete . Delete (); // delete the record
     m_setComplete . MoveFirst (); // move back to the first record
m_bRecordsWereDeleted = TRUE; // make a note that we changed the database
SetDlgItemText ( IDC_Delete_STATUS, "Repeater Deleted From Database" ); // set the status field
}else{
// if we EVER end up here, either the database is in the crapper, or I will have screwed up horribly--been known to happen from time
//to time , so let's cover our ass-ets just in case.
AfxMessageBox ( "Internal failure/n/nCannot find selected repeater in database/nor database is corrupted", MB_ICONSTOP );
}
m_setComplete . Close (); // close the database*/

/* 1, ODBC 數據庫,不是ADO
m_setComplete.m_strFilter="number=200301";//條件查詢(where語句)
if ( ! m_setComplete . IsOpen () )
m_setComplete . Open ();
m_setComplete.Delete();
m_setComplete . MoveFirst ();
m_setComplete . Close (); // close the database
m_setComplete.m_strFilter="";//清空條件(where語句)
//查詢(where語句)
m_setComplete.m_strFilter="number=200301";
if ( ! m_setComplete . IsOpen () )
m_setComplete . Open ();
m_setComplete . Close (); // close the database

//不用類嚮導寫連接數據庫的程序段,但是我只看明白了連接和查詢,不會修改和添加,刪除
//1,
CDatabase m_dbCust; //定義數據庫類對象
m_dbCust.OpenEx(_T("DSN=MQIS;UID=sa;PWD=1980623")//打開數據庫 //數據源名,用戶名,密碼 ,CDatabase::forceOdbcDialog );//此參數只定是//否打開連接確認對話框
//MessageBox(m_dbCust.GetDatabaseName()); 取得數據源名
//m_dbCust.ExecuteSQL("select number from works");測試是否支持SQL語句
CRecordset cs(&m_dbCust);//定義目錄查詢對象
cs.Open( CRecordset::dynaset,
_T( "select * from works" ) );//打開時執行的SQL語句
short nFields = cs.GetODBCFieldCount( );//取得字段數,(列數)
CDBVariant varValue;//定義通用數據類型
CODBCFieldInfo co;//定義字段信息
CString cc;
while( !cs.IsEOF( ) )
{
for( short index = 0; index < nFields; index++ )
{
// do something with varValue
cs.GetFieldValue(index,varValue);//取得某列的數據,
//cs.GetFieldValue(index,cc); 也可直接取得由某列的數據直接轉化成的文本
if(varValue.m_dwType==DBVT_LONG)//m_dwType成員用來判斷數據類型
/* m_dwType Union data member
DBVT_NULL No union member is valid for access.
DBVT_BOOL m_boolVal
DBVT_UCHAR m_chVal
DBVT_SHORT m_iVal
DBVT_LONG m_lVal
DBVT_SINGLE m_fltVal
DBVT_DOUBLE m_dblVal
DBVT_DATE m_pdate
DBVT_STRING m_pstring
DBVT_BINARY m_pbinary
*/
{
cc.Format("%d",varValue.m_lVal);//m_dwType==DBVT_LONG時爲LONG型數據,成員爲m_lVal,數值在其中
MessageBox(cc);
}
cs.GetODBCFieldInfo(index,co);//取得字段信息
/* struct CODBCFieldInfo
{
CString m_strName;    字段名
SWORD m_nSQLType;    SQL數據類型
UDWORD m_nPrecision;
SWORD m_nScale;
SWORD m_nNullability;
};
*/
} //for
cs.MoveNext( );//下一個
}
cs.Close();

………10,顯示程序段*
CString cstr;
cstr.Format("%d", );
MessageBox(cstr);
if(MessageBox("關閉Windows祕書您可會失去重要的提醒信息,確定要關閉嗎?",
"Windows祕書",
MB_OKCANCEL|MB_DEFBUTTON2|MB_ICONWARNING)==IDOK)
MessageBeep(MB_ICONQUESTION);

………11,註冊與卸載OCX控件
//1,函數入口宏定義
typedef HRESULT (STDAPICALLTYPE *CTLREGPROC)();
//2,註冊函數
BOOL RegisterOcx(CString ocxfilename)
{
BOOL bResult = FALSE ;
HMODULE hModule = ::LoadLibrary(ocxfilename) ;
//獲得註冊函數地址
CTLREGPROC DLLRegisterServer =
(CTLREGPROC)::GetProcAddress(hModule,"DllRegisterServer" ) ;
if (DLLRegisterServer != NULL)
{
HRESULT regResult = DLLRegisterServer() ;
bResult = (regResult == NOERROR) ;
}
::FreeLibrary(hModule) ;
return bResult ;
}
//2,卸載函數
BOOL UnRegisterOcx(CString ocxfilename)
{
BOOL bResult = FALSE ;
HMODULE hModule = ::LoadLibrary(ocxfilename) ;
//獲得卸載函數地址
CTLREGPROC DLLUnregisterServer =
(CTLREGPROC)::GetProcAddress( hModule, "DllUnregisterServer" ) ;
if (DLLUnregisterServer != NULL)
{
HRESULT regResult = DLLUnregisterServer() ;
bResult = (regResult == NOERROR) ;
}
::FreeLibrary(hModule) ;
return bResult ;
}

………12,處理文件拖動
//1 添加 WM_DropFILES 靜態消息
//2 在OnInitDialog()函數中加入
DragAcceptFiles(TRUE);//允許拖放
//3 WM_DropFILES 的處理函數爲
void CCXatDemoDlg::OnDropFiles(HDrop hDropInfo)
{
unsigned int nFiles=DragQueryFile(hDropInfo,0xFFFFFFFF,NULL,0);//取得拖放的文件總數
for (unsigned int i=0;i<nFiles;i++)//循環取得文件名
{
unsigned int nLen=DragQueryFile(hDropInfo,i,NULL,0)+1;//取得文件名長度
char *psBuffer=new char[nLen];
unsigned int sLen=DragQueryFile(hDropInfo,i,psBuffer,nLen);//取得文件名到psBuffer中,sLen爲實際拷貝的字符數
//To add code here...
          
delete [] psBuffer;
}
DragFinish(hDropInfo);//結束
}

………13,設置窗口大小和位置
SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);//設爲最高層
/*
wndBottom
wndTop
wndTopMost
wndNoTopMost
*/
//在窗體中這樣做 HWND_NOTOPMOST 爲不是最高層
::SetWindowPos(AfxGetMainWnd()->m_hWnd,HWND_TOPMOST,-1,-1,-1,-1,SWP_NOMOVE|SWP_NOSIZE);
/*
HWND_BOTTOM
HWND_NOTOPMOST
HWND_TOP
HWND_TOPMOST
SWP_DRAWFRAME Draws a frame, defined in the class description of the window, around the window.
SWP_FRAMECHANGED Sends a WM_NCCALCSIZE message to the window, even if the size of the window is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the size of the window is being changed.
SWP_HIDEWINDOW Hides the window.
SWP_NOACTIVATE Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or nontopmost group, depending on the setting of the hWndInsertAfter parameter.
SWP_NOMOVE Retains the current position and ignores the X and Y parameters.
SWP_NOOWNERZORDER Does not change the position in the Z order of the owner window.
SWP_NOREPOSITION Same as the SWP_NOOWNERZORDER flag.
SWP_NOSIZE Retains the current size and ignores the cx and cy parameters.
SWP_NOZORDER Retains the current Z order and ignores the hWndInsertAfter parameter.
SWP_SHOWWINDOW Displays the window.
*/

………14,在系統欄顯示圖標
//1定義結構
NOTIFYICONDATA systemicon;
//2定義新的消息
#define WM_SYSTEMMESSAGE WM_USER+998
//3添加消息函數映射
ON_MESSAGE(WM_SYSTEMMESSAGE,OnSystemMessage)
//4初始化結構
systemicon.cbSize=sizeof(NOTIFYICONDATA);
systemicon.hWnd=this->m_hWnd;
systemicon.uID=IDI_SYSICON; //圖標
systemicon.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
systemicon.uCallbackMessage=WM_SYSTEMMESSAGE;
systemicon.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_SYSICON));
strcpy(systemicon.szTip,"Windows祕書");
Shell_NotifyIcon(NIM_ADD,&systemicon);//顯示
strcpy(systemicon.szTip,cs);
Shell_NotifyIcon(NIM_MODIFY,&systemicon);//修改
Shell_NotifyIcon(NIM_Delete,&systemicon);//刪除
//處理函數
void OnSystemMessage(WPARAM wParam, LPARAM lParam)
{
if(wParam!=IDI_SYSICON)
return;
switch(lParam)
{
case WM_RBUTTONUP://右鍵起來時彈出快捷菜單
{
CMenu *menu=NULL;
LPPOINT mousepoint=new tagPOINT;
::GetCursorPos(mousepoint);//得到鼠標位置
BCMenu bmpmenu;
bmpmenu.LoadMenu(IDR_SYSPOPUPMENU);
menu = bmpmenu.GetSubMenu (0);//確定彈出式菜單的位置
if (IsWindowVisible())
bmpmenu.ModifyODMenuA("隱藏主窗口",ID_SHOWHIDE,IDB_HIDE);
else
bmpmenu.ModifyODMenuA("顯示主窗口",ID_SHOWHIDE,IDB_SHOW);
if (findtxdata->stoplowstep==0)
bmpmenu.ModifyODMenuA("停止普通級提醒",ID_STOPALLPT,IDB_STOP);
else
bmpmenu.ModifyODMenuA("啓用普通級提醒",ID_STOPALLPT,IDB_NOTSTOP);
if (topornot)
bmpmenu.ModifyODMenuA("窗體不在最上層",ID_NOTONTOP,IDB_NOTTOP);
else
bmpmenu.ModifyODMenuA("窗體在最上層",ID_NOTONTOP,IDB_TOP);
if (!muteornot)
bmpmenu.ModifyODMenuA("靜音",IDMUTE,IDB_NOSOUND);
else
bmpmenu.ModifyODMenuA("取消靜音",IDMUTE,IDB_SOUND);
SetForegroundWindow();//必須先調用這個函數才能如果我不選擇任何菜單而取消它
menu->TrackPopupMenu(TPM_LEFTALIGN,mousepoint->x,mousepoint->y,this);
//資源回收
//menu->Detach();
//menu->DestroyMenu();
delete mousepoint;
break;
}
}
return;
}

………15,浮動鼠標提示
//1定義
CToolTipCtrl tooltip;
//2在OnCreate函數中創建
tooltip.Create(this);
//3在OnInitDialog函數中爲控件添加提示字符
tooltip.AddTool(GetDlgItem(IDC_DATEANDTIME),"顯示日期/時間");
tooltip.Activate(TRUE);//啓動
//4在PreTranslateMessage(MSG* pMsg) 函數中加上
tooltip.RelayEvent(pMsg);

………16,tab控件的使用
m_tab.InsertItem(0,"提醒");
//定義結構
WINDOWPLACEMENT wininfo;
//取得窗口信息
m_tab.GetWindowPlacement(&wininfo);
//注意第一個參數要爲&wndTop,如果是&wndTopMost就可能會函數功能無效
qita.SetWindowPos(&wndTop,wininfo.rcNormalPosition.left-10,wininfo.rcNormalPosition.top+20,0,0,SWP_NOSIZE|SWP_HIDEWINDOW);
//選擇不同的標籤
void OnSelchangeTab(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
int i=m_tab.GetCurSel();
switch(i)
{
case 0:
break;
case 1:
break;
}
*pResult = 0;
}

………17,註冊熱鍵
//m_filehotkey爲熱鍵控件變量
m_filehotkey.GetHotKey(WORD virtualkey,WORD flags);
//注意要在主窗口中調用這個函數
void RegHotKey(WORD virtualkey,WORD flags,int id)
{
if (flags==1||flags==9)//從熱鍵控件中得到的系統鍵與下函數的標誌不同,但有一一對應的關係:
{
RegisterHotKey(GetSafeHwnd(),id,MOD_SHIFT,virtualkey);
}//每個ID只能註冊一個熱鍵,up,down,home,end等中部鍵盤的鍵的flags爲9,10,11,12,13,14,15
if (flags==2||flags==10)//其餘爲1,2,3,4,5,6,7
{
RegisterHotKey(GetSafeHwnd(),id,MOD_CONTROL,virtualkey);
}
if (flags==4||flags==12)
{
RegisterHotKey(GetSafeHwnd(),id,MOD_ALT,virtualkey);
}
if (flags==3||flags==11)
{
RegisterHotKey(GetSafeHwnd(),id,MOD_CONTROL|MOD_SHIFT,virtualkey);
}
if (flags==5||flags==13)
{
RegisterHotKey(GetSafeHwnd(),id,MOD_ALT|MOD_SHIFT,virtualkey);
}
if (flags==6||flags==14)
{
RegisterHotKey(GetSafeHwnd(),id,MOD_ALT|MOD_CONTROL,virtualkey);
}
if (flags==7||flags==15)
{
RegisterHotKey(GetSafeHwnd(),id,MOD_ALT|MOD_CONTROL|MOD_SHIFT,virtualkey);
}
}
//處理消息
LRESULT CWindowsDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch(message)
{
case WM_HOTKEY :
switch(wParam)
{
case IDC_HOTKEY:
if (IsWindowVisible())
ShowWindow(SW_HIDE);
else
ShowWindow(SW_SHOWNORMAL);
SetForegroundWindow();
break;
case IDC_HOTKEY2:
break;
}
return 0 ;
}
return CDialog::WindowProc(message, wParam, lParam);
}

………18,控制系統音量
// 在StdAfx.h中加入宏
#include <mmsystem.h>
// 在setting->Link中加入下靜態鏈接庫:winmm.lib
// 播放聲音 文件名 風格:第一個參數爲文件名/找不到文件時不播放默認聲音
PlaySound( "", NULL, SND_FILENAME |SND_NODEFAULT);
// 定義結構
UINT m_nNumMixers; //混合器的數量
HMIXER m_hMixer; //當前混合器的句柄
MIXERCAPS m_mxcaps; //當前混合器的性能參數
CString m_strDstLineName, m_strVolumeControlName; //混合器控件的名稱
DWORD m_dwMinimum, m_dwMaximum; //最大,最小的音量值
DWORD m_dwVolumeControlID; //混合器控件的音量控制ID
DWORD m_dwMuteControlID; //混合器控件的靜音控制ID
BOOL muteornot; //是否靜音
DWORD nowvolume; //當前值
double multiple;
double difference; //最大最小差值
int volumestep;//步長
// 加入消息映射函數
ON_MESSAGE(MM_MIXM_CONTROL_CHANGE, OnMixerCtrlChange)
// 當系統音量改變時調用此函數
LONG OnMixerCtrlChange(UINT wParam, LONG lParam)
{
//響應控件音量改變的消息,然後獲得當前音量並設置滾動條
if ((HMIXER)wParam == m_hMixer && (DWORD)lParam == m_dwVolumeControlID)
{
amdGetMasterVolumeValue(nowvolume);
multiple=nowvolume;
double percent;
}
if ((HMIXER)wParam == m_hMixer && (DWORD)lParam == m_dwMuteControlID)
{
amdGetMasterMuteValue(muteornot);
}
return 0L;
}
// 在Init函數中加入
if (amdInitialize())
{
//獲得音量控制控件的ID和名稱
amdGetMasterVolumeControl();
// 獲得當前音量值,並設置滾動條的初始位置
amdGetMasterVolumeValue(nowvolume);
amdGetMasterMuteValue(muteornot);
multiple=nowvolume;
difference=(long)(m_dwMaximum-m_dwMinimum);
}
// 函數
BOOL amdInitialize()//初始化
{
//獲取當前混合設備數量
m_nNumMixers = ::mixerGetNumDevs();
m_hMixer = NULL;
::ZeroMemory(&m_mxcaps, sizeof(MIXERCAPS));
if (m_nNumMixers != 0)
{
//打開混合設備
if (::mixerOpen(&m_hMixer,
0,
(DWORD)this->GetSafeHwnd(),
NULL,
MIXER_OBJECTF_MIXER | CALLBACK_WINDOW) != MMSYSERR_NOERROR)
return FALSE;

// 獲取混合器性能
if  (::mixerGetDevCaps((UINT)m_hMixer, &m_mxcaps, sizeof(MIXERCAPS))!= MMSYSERR_NOERROR)
return FALSE;
}
return TRUE;
}
BOOL amdGetMasterVolumeControl()//獲得音量控制控件的ID和名稱
{
m_strDstLineName.Empty();
m_strVolumeControlName.Empty();
if (m_hMixer == NULL)
return FALSE;
//獲得混合器性能
MIXERLINE mxl;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
if (::mixerGetLineInfo((HMIXEROBJ)m_hMixer,
&mxl,
MIXER_OBJECTF_HMIXER |
MIXER_GETLINEINFOF_COMPONENTTYPE)!= MMSYSERR_NOERROR)
return FALSE;
MIXERCONTROL mxc;
MIXERLINECONTROLS mxlc;
mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;//此值表示取得音量
mxlc.cControls = 1;
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
mxlc.pamxctrl = &mxc;
//獲得混合器線控件
if (::mixerGetLineControls((HMIXEROBJ)m_hMixer,
&mxlc,
MIXER_OBJECTF_HMIXER |
MIXER_GETLINECONTROLSF_ONEBYTYPE)!= MMSYSERR_NOERROR)
return FALSE;
//記錄控件的信息
m_strDstLineName = mxl.szName;
m_strVolumeControlName = mxc.szName;
m_dwMinimum = mxc.Bounds.dwMinimum;
m_dwMaximum = mxc.Bounds.dwMaximum;
m_dwVolumeControlID = mxc.dwControlID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;//此值表示取得靜音與否
if (::mixerGetLineControls((HMIXEROBJ)m_hMixer,
&mxlc,
MIXER_OBJECTF_HMIXER |
MIXER_GETLINECONTROLSF_ONEBYTYPE)!= MMSYSERR_NOERROR)
return FALSE;
m_dwMuteControlID = mxc.dwControlID;
return TRUE;
}
BOOL amdGetMasterVolumeValue(DWORD &dwVal)// 獲得當前音量值,並設置滾動條的初始位置
{
if (m_hMixer == NULL || m_strDstLineName.IsEmpty() || m_strVolumeControlName.IsEmpty())
return FALSE;
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
MIXERCONTROLDETAILS mxcd;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = m_dwVolumeControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxcdVolume;
//獲取指定混合器控件
if (::mixerGetControlDetails((HMIXEROBJ)m_hMixer,
&mxcd,
MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
return FALSE;
dwVal = mxcdVolume.dwValue;
return TRUE;
}
BOOL amdGetMasterMuteValue(BOOL &yorn)//是否靜音
{
if (m_hMixer == NULL || m_strDstLineName.IsEmpty() || m_strVolumeControlName.IsEmpty())
return FALSE;
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
MIXERCONTROLDETAILS mxcd;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = m_dwMuteControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxcdVolume;
//獲取指定混合器控件
if (::mixerGetControlDetails((HMIXEROBJ)m_hMixer,
&mxcd,
MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
return FALSE;
yorn = mxcdVolume.dwValue;
return TRUE;
}
BOOL amdSetMasterMuteValue(BOOL &yorn)//設置靜音與否
{
if (m_hMixer == NULL || m_strDstLineName.IsEmpty() || m_strVolumeControlName.IsEmpty())
return FALSE;
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume = { yorn };
MIXERCONTROLDETAILS mxcd;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = m_dwMuteControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxcdVolume;
//放置混合器控件
if (::mixerSetControlDetails((HMIXEROBJ)m_hMixer,
&mxcd,
MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
return FALSE;
return TRUE;
}
BOOL amdSetMasterVolumeValue(DWORD dwVal)//設置音量
{
if (m_hMixer == NULL || m_strDstLineName.IsEmpty() || m_strVolumeControlName.IsEmpty())
return FALSE;
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume = { dwVal };
MIXERCONTROLDETAILS mxcd;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = m_dwVolumeControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxcdVolume;
//放置混合器控件
if (::mixerSetControlDetails((HMIXEROBJ)m_hMixer,
&mxcd,
MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
return FALSE;
return TRUE;
}
BOOL amdUninitialize()//關閉
{
BOOL bSucc = TRUE;
if (m_hMixer != NULL)
{
//關閉混合器
bSucc = ::mixerClose(m_hMixer) == MMSYSERR_NOERROR;
m_hMixer = NULL;
}
return bSucc;
}
//在OnDestroy() 中加入
amdUninitialize();

………19,編輯註冊表
DWORD disp,valuelength=260;
HKEY parentkey;
HKEY childkey;
char filepath[MAX_PATH];
//打開主鍵
RegOpenKeyEx(HKEY_LOCAL_MACHINE,"software//microsoft//windows//currentversion//run",//註冊啓動信息 0L,KEY_WRITE,&parentkey);
//查詢鍵值
RegQueryValueEx(parentkey,"Windows祕書",0,NULL,(unsigned char *)filepath,&valuelength);
//寫入鍵值
RegSetValueEx(parentkey,"Windows祕書",0,REG_SZ,(const unsigned char *)filepath,strlen(filepath));
//刪除鍵值
RegDeleteValue(parentkey,"Windows祕書");
//關閉
RegCloseKey(parentkey);
//建立子鍵
RegOpenKeyEx(HKEY_LOCAL_MACHINE,"software",
0L,KEY_WRITE,&parentkey);//打開主鍵
RegCreateKeyEx(parentkey,"宇光軟件",NULL,"CWindowsDlg",REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,
NULL,&childkey,&disp);//把子鍵保存在childkey中
RegCloseKey(parentkey);
//在子鍵中寫入子鍵值
RegSetValueEx(childkey,"Windows祕書",0,REG_SZ,(const unsigned char *)filepath,strlen(filepath));
RegCloseKey(childkey);

………20,創建桌面快捷圖標和創建開始菜單組
//初始化
CoInitialize (NULL);
//建立桌面快捷圖標函數
void CreateDesttop(char *filepath)

{
strcat(filepath,"//Windows祕書.exe");
LPITEMIDLIST pidlBeginAt;
char szLink[MAX_PATH]="";//快捷方式的數據文件名
// 取得桌面的PIDL
SHGetSpecialFolderLocation( HWND_DESKTOP,CSIDL_DESKTOPDIRECTORY, &pidlBeginAt) ;
// 把PIDL轉換爲路徑名
SHGetPathFromIDList( pidlBeginAt, szLink) ;
strcat(szLink,"//Windows祕書.lnk");
IShellLink * psl ;
IPersistFile* ppf ;
WORD wsz[ MAX_PATH] ;
//創建一個IShellLink實例
CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl) ;
//設置目標應用程序
psl -> SetPath( filepath) ;
//設置快捷鍵(此處設爲Shift+Ctrl+'R')
psl -> SetHotkey( MAKEWORD( 'Q', HOTKEYF_SHIFT |HOTKEYF_CONTROL|HOTKEYF_ALT)) ;
//從IShellLink獲取其IPersistFile接口
//用於保存快捷方式的數據文件 (*.lnk)
psl -> QueryInterface( IID_IPersistFile, (void**)&ppf) ;
// 確保數據文件名爲ANSI格式
MultiByteToWideChar( CP_ACP, 0, szLink, -1, wsz, MAX_PATH) ;
//調用IPersistFile::Save
//保存快捷方式的數據文件 (*.lnk)
ppf -> Save( wsz, STGM_READWRITE) ;
//釋放IPersistFile和IShellLink接口
ppf -> Release( ) ;
psl -> Release( ) ;

SHChangeNotify( SHCNE_Create|SHCNE_INTERRUPT,SHCNF_FLUSH | SHCNF_PATH, szLink,0);
//取得szPath的父目錄
char* p;
for( p=szLink+lstrlen(szLink)-1; *p != '//'; p--);
*p='/0';
SHChangeNotify(SHCNE_UpdateDIR |SHCNE_INTERRUPT,SHCNF_FLUSH | SHCNF_PATH,szLink,0);
}
//創建開始菜單組的函數
void CWindowsDlg::CreateStarMenu(char *filepath)
{
LPITEMIDLIST pidlBeginAt;
char szPath[ MAX_PATH] ;
// 取得開始菜單的PIDL
SHGetSpecialFolderLocation( HWND_DESKTOP, CSIDL_STARTMENU, &pidlBeginAt) ;
SHGetPathFromIDList( pidlBeginAt, szPath) ;// 把PIDL轉換爲路徑名
strcat(szPath,"//宇光軟件");
if( !CreateDirectory( szPath, NULL))return ;
SHChangeNotify( SHCNE_MKDIR|SHCNE_INTERRUPT, SHCNF_FLUSH | SHCNF_PATH, szPath,0);
//取得szPath的父目錄
char* p;
for( p=szPath+lstrlen(szPath)-1;*p != '//'; p--);
*p='/0';
SHChangeNotify(SHCNE_UpdateDIR |SHCNE_INTERRUPT, SHCNF_FLUSH | SHCNF_PATH,szPath,0);
strcat(filepath,"//Windows祕書.exe");
strcat(szPath,"//宇光軟件//Windows祕書.lnk");
IShellLink * psl ;
IPersistFile* ppf ;
WORD wsz[ MAX_PATH] ;
//創建一個IShellLink實例
CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl) ;
//設置目標應用程序
psl -> SetPath( filepath) ;
//設置快捷鍵(此處設爲Shift+Ctrl+'Y')
psl -> SetHotkey( MAKEWORD( 'Y', HOTKEYF_SHIFT |HOTKEYF_CONTROL|HOTKEYF_ALT)) ;
//從IShellLink獲取其IPersistFile接口
//用於保存快捷方式的數據文件 (*.lnk)
psl -> QueryInterface( IID_IPersistFile, (void**)&ppf) ;
// 確保數據文件名爲ANSI格式
MultiByteToWideChar( CP_ACP, 0, szPath, -1,wsz, MAX_PATH) ;
//調用IPersistFile::Save
//保存快捷方式的數據文件 (*.lnk)
ppf -> Save( wsz, STGM_READWRITE) ;
//釋放IPersistFile和IShellLink接口
ppf -> Release( ) ;
psl -> Release( ) ;

SHChangeNotify( SHCNE_Create|SHCNE_INTERRUPT, SHCNF_FLUSH | SHCNF_PATH, szPath,0);
//取得szPath的父目錄
for( p=szPath+lstrlen(szPath)-1; *p != '//'; p--);
*p='/0';
SHChangeNotify(SHCNE_UpdateDIR |SHCNE_INTERRUPT, SHCNF_FLUSH | SHCNF_PATH,szPath,0);
}
void OnDestroy()
{
CoUninitialize();
}

………21,程序只允許一個實例運行
//在這個位置調用FirstInstance函數
BOOL CWindowsApp::InitInstance()
{
if (!FirstInstance())
return FALSE; //已經有實例存在了,退出
AfxEnableControlContainer();
}
//FirstInstance函數
BOOL FirstInstance()
{
CWnd *pWndPrev;
//根據主窗口類名和主窗口名判斷是否已經有實例存在了
if (pWndPrev = CWnd::FindWindow("#32770","Windows祕書"))//第二個參數爲程序名
{
//如果存在就將其激活,並顯示出來
pWndPrev->ShowWindow(SW_RESTORE);
pWndPrev->SetForegroundWindow();
return FALSE;
}else{
return TRUE;
}
}

………22,取得系統時間及計算時間差
DWORD system_runtime;
system_runtime=GetTickCount()/60000;//取得系統運行時間
SYSTEMTIME sysTime; // Win32 time information
GetLocalTime(&sysTime);
COleDateTime now(sysTime);
//COleDateTime now;
//now=now.GetCurrentTime();
//GetCurrentTime()取得時間與time( time_t *timer );和struct tm *localtime( const time_t *timer );所得時間相同只能到2037年
//而GetLocalTime(&sysTime);可到9999年
m_zbyear=now.GetYear();//年
m_zbmonth=now.GetMonth();//月
m_zbday=now.GetDay();//日
now.GetDayOfWeek();//weekday
COleDateTimeSpan sub;
sub.SetDateTimeSpan(m_howdaysafteris,0,0,0);//設定時間差爲天數
now+=sub;
then.SetDateTime(,,,,,,,);//其它方式添加時保存的當時時間
if(!now.SetDate(m_jsyear,m_jsmonth,m_jsday)//檢查時間是否正確 &&!then.SetDate(m_jsyear2,m_jsmonth2,m_jsday2))
{
sub=then-now;
CString cs;
cs.Format("%d年%d月%d日 相距 %d年%d月%d日/n/n %.0f天",m_jsyear,m_jsmonth,m_jsday,
m_jsyear2,m_jsmonth2,m_jsday2,sub.GetTotalDays());
MessageBox(cs);
}
else
MessageBox("您輸入的時間有誤,請重新輸入!","Windows祕書",MB_OK|MB_ICONSTOP);

………23,文件操作
//打開文件對話框
CFileDialog dlg(TRUE, "mp3", NULL, OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR,
"音樂/電影文件(*.mp3,*.wav,*.avi,*.asf)|*.mp3;*.wav;*.avi;*.asf|"/
"mp3 文件(*.mp3)|*.mp3|" /
"音頻文件 (*.wav)|*.wav|" /
"視頻文件 (*.avi)|*.avi|" /
"Window Media 文件(*.asf)|*.asf|" /
"所有文件 (*.*)|*.*||");
if(dlg.DoModal()==IDOK)
{
CString m_filename=dlg.GetPathName();
}
//讀取文件
CFile file;
If (file.Open(m_filename,CFile::modeRead))
{
file.Read(zbpassword,sizeof(zbpassword));
}
file.Close();
//寫入文件
if (file.Open(m_zbfilename,CFile::modeCreate|CFile::modeWrite))
{
zbfile.Write(zbpassword,sizeof(zbpassword));
}
file.Close();

………24,進制轉換
CString BinaryToDecimal(CString strBinary)//轉換二進制爲十進制
{
int nLenth = strBinary.GetLength();
char* Binary = new char[nLenth];
Binary = strBinary.GetBuffer(0);
int nDecimal = 0;
for(int i=0;i<nLenth;i++)
{
char h = Binary[nLenth-1-i];
char str[1];
str[0] = h;
int j = atoi(str);
for(int k=0;k<i;k++) j=j*2;  
nDecimal += j;
}
CString strDecimal;
strDecimal.Format("%d",nDecimal);
return strDecimal;
}
CString BinaryToHex(CString strBinary)//轉換二進制爲十六進制
{
int nLength = strBinary.GetLength();
CString str = strBinary;
//位數不是四的倍數時補齊
switch(nLength%4)
{
case 0:
break;
case 1:
strBinary.Format("%d%d%d%s",0,0,0,str);
break;
case 2:
strBinary.Format("%d%d%s",0,0,str);
break;
case 3:
strBinary.Format("%d%s",0,str);
break;
default:
return "";
break;
}
CString strHex,str1;
str1 = "";
nLength = strBinary.GetLength();
for(int i=1;i<=(nLength/4);i++)
{
//每四位二進制數轉換爲一十六進制數
str = strBinary.Left(4);
CString strDecimal = BinaryToDecimal(str);
int nDecimal = atoi(strDecimal.GetBuffer(0));
if (nDecimal<10)
str1.Format("%d",nDecimal);
else
{
char c = 'A' + (nDecimal-10);
str1.Format("%c",c);
}
strHex += str1;
strBinary = strBinary.Right(strBinary.GetLength()-str.GetLength());
}
return strHex;
}
unsigned char BtoH(char ch)//將16進制的一個字符轉換爲十進制的數
{
//0-9
if (ch >= '0' && ch <= '9')
return (ch - '0');
//9-15
if (ch >= 'A' && ch <= 'F')
return (ch - 'A' + 0xA);
//9-15
if (ch >= 'a' && ch <= 'f')
return (ch - 'a' + 0xA);
return(255);
}
CString DecimalToBinary(CString strDecimal)//轉換十進制爲二進制
{
int nDecimal = atoi(strDecimal.GetBuffer(0));
int nYushu; //餘數
int nShang; //商
CString strBinary = "";
char buff[2];
CString str = "";
BOOL bContinue = TRUE;
while(bContinue)
{
nYushu = nDecimal%2;
nShang = nDecimal/2;
sprintf(buff,"%d",nYushu);
str = strBinary;
strBinary.Format("%s%s",buff,str);
nDecimal = nShang;
if(nShang==0)
bContinue = FALSE;
}
return strBinary;
}

CString BinaryToDecimal(CString strBinary)//轉換二進制爲十進制
{
int nLenth = strBinary.GetLength();
char* Binary = new char[nLenth];
Binary = strBinary.GetBuffer(0);
int nDecimal = 0;
for(int i=0;i<nLenth;i++)
{
char h = Binary[nLenth-1-i];
char str[1];
str[0] = h;
int j = atoi(str);
for(int k=0;k<i;k++) j=j*2;  
nDecimal += j;
}
CString strDecimal;
strDecimal.Format("%d",nDecimal);
return strDecimal;
}

………25,數學函數
sin();
cos();
tan();
sqrt();
pow(x,y);
log();
log10();

………26,遞歸法遍歷磁盤目錄
void CQt::BrowseDir(CString strDir)
{
CFileFind ff;
CString str,cs,inifile;
inifile=regfilepath;
inifile+="//Windows祕書.ini";
CString szDir = strDir;
int index;
char jjj,ppp,ggg;
if(szDir.Right(1) != "//")
szDir += "//";
szDir += "*.*";
BOOL res = ff.FindFile(szDir);
while(res)
{
res = ff.FindNextFile();
if(ff.IsDirectory() && !ff.IsDots())
{
//如果是一個子目錄,用遞歸繼續往深一層找
BrowseDir(ff.GetFilePath());
}
else if(!ff.IsDirectory() && !ff.IsDots())
{
//顯示當前訪問的文件
str=ff.GetFilePath();
/* index=str.GetLength();
//MessageBox(str);
jjj=str.GetAt(index-3);
ppp=str.GetAt(index-2);
ggg=str.GetAt(index-1);
if(((jjj=='J'||jjj=='j')&&(ppp=='P'||ppp=='p')&&(ggg=='G'||ggg=='g'))||((jjj=='B'||jjj=='b')&&(ppp=='M'||ppp=='m')&&(ggg=='P'||ggg=='p')))
{
intNumber++;
cs.Format("%d",intNumber);
WritePrivateProfileString("圖片目錄文件",cs,str,inifile);*/
//Sleep(3);
}
}
}
ff.Close();//關閉
//cs.Format("%d",intNumber);
//WritePrivateProfileString("圖片目錄文件","total",cs,inifile);
//WritePrivateProfileString("圖片目錄文件","turntowhich","1",inifile);
}

//公用目錄對話框****************************************************

//添加如下程序段
LPITEMIDLIST pidlBeginAt, pidlDestination ;
char szPath[ MAX_PATH] ;
// 取得開始菜單或桌面的PIDL
SHGetSpecialFolderLocation(AfxGetApp()->m_pMainWnd->m_hWnd,CSIDL_DESKTOP,&pidlBeginAt) ;
// 取得新建文件夾的父文件夾
if( !BrowseForFolder(pidlBeginAt ,
&pidlDestination,
"請選擇圖片目錄的位置:"))
{
return ;
}
// 把PIDL轉換爲路徑名
SHGetPathFromIDList( pidlDestination, szPath);
//添加如下函數
BOOL BrowseForFolder(
LPITEMIDLIST pidlRoot,//瀏覽開始處的PIDL
LPITEMIDLIST *ppidlDestination,
//瀏覽結束時所選擇的PIDL
LPCSTR lpszTitle)//瀏覽對話框中的提示文字
{
BROWSEINFO BrInfo ;
ZeroMemory( &BrInfo, sizeof(BrInfo)) ;
BrInfo.hwndOwner = HWND_DESKTOP ;
BrInfo.pidlRoot = pidlRoot ;
BrInfo.lpszTitle = lpszTitle ;
//瀏覽文件夾
*ppidlDestination= SHBrowseForFolder(&BrInfo);
//用戶選擇了取消按鈕
if(NULL == *ppidlDestination)
return FALSE ;/**/
return TRUE ;
}

//讀寫INI/ini文件*************************************************

//寫入值 字段名 變量名 值 帶目錄文件名
WritePrivateProfileString("目錄","path",cs, regpath);
//寫入結構體 字段名 變量名 值 大小 帶目錄文件名
WritePrivateProfileStruct("字體","font",&LF,sizeof(LOGFONT),regpath);//結構體
//讀入字符 字段名 變量名 默認值 字符緩衝區 長度 帶目錄文件名
GetPrivateProfileString("目錄","path","", buffer.GetBuffer(260),260,regpath);
//讀入整數值 字段名 變量名 默認值 帶目錄文件名
GetPrivateProfileInt("colors","red",255, regpath);
//讀入結構體 字段名 變量名 值 大小 帶目錄文件名
GetPrivateProfileStruct("字體","font",&LF,sizeof(LOGFONT),regpath);

//位圖操作,畫圖*****************************************************

CClientDC client(this);
BITMAP bmpInfo;
CDC memdc;
CBitmap picture;
memdc.CreateCompatibleDC(pdc);
memdc.SelectObject(&picture);
CRect re;
GetClientRect(&re);
client.BitBlt(0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,&memdc,0,0,SRCCOPY);
client.SetBkMode(TRANSPARENT);
client.SetTextColor(RGB(red,green,blue));
CFont font;
CFont *oldfont;
font.CreateFontIndirect(&LF);
oldfont=client.SelectObject(&font);
client.DrawText("",//注意這個字符串裏如果只有一連串的字母或數字,沒有空格或中文或標點符號,且總長度超過距形寬度,則不能自動換行!!
&re,DT_CENTER |DT_WORDBREAK);
client.SelectObject(oldfont);

//打開EXE/exe文件**********************************************

ShellExecute(GetSafeHwnd(),
"open",
"http://home.jlu.edu.cn/~ygsoft",//改這個文件名就可以了
NULL,
NULL,SW_SHOWNORMAL);
//or
LPITEMIDLIST pidlBeginAt;
// 取得桌面的PIDL
SHGetSpecialFolderLocation(AfxGetApp()->m_pMainWnd->m_hWnd,
CSIDL_DRIVES//這個標誌爲我的電腦
,&pidlBeginAt) ;
SHELLEXECUTEINFO exe;
ZeroMemory(&exe,sizeof(SHELLEXECUTEINFO));
exe.cbSize=sizeof(SHELLEXECUTEINFO);
exe.fMask=SEE_MASK_IDLIST;
exe.lpVerb="open";
exe.nShow=SW_SHOWNORMAL;
exe.lpIDList=pidlBeginAt;
ShellExecuteEx(&exe);

//取得函數不能正常返回的原因字符***************************

LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_InsertS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
MessageBox((LPCTSTR)lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );

//關機函數************************************************

void ShutDown(void)//2000 or NT
{
OSVERSIONINFO osv;
osv.dwOSVersionInfoSize=sizeof OSVERSIONINFO;
GetVersionEx(&osv);
if(osv.dwPlatformId==VER_PLATFORM_WIN32_NT)//VER_PLATFORM_WIN32_WINDOWS 98 Me用這個宏
{
HANDLE hProcess,hToken;
TOKEN_PRIVILEGES Privileges;
LUID luid;
hProcess=GetCurrentProcess();
OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES,&hToken);
Privileges.PrivilegeCount=1;
LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&luid);
Privileges.Privileges[0].Luid=luid;
Privileges.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken,FALSE,&Privileges,NULL,NULL,NULL);
}
ExitWindowsEx(EWX_POWEROFF,0);
}

//***************************************

//創建一個非模態對話框,如
//1聲明父對話框
#include "Tx.h"
//2在頭文件中改爲CTx* pParent = NULL,並聲明CTx *tx;
public:
CInputmr(CTx* pParent = NULL); // standard constructor
CTx *tx;
//3在CPP文件中改爲CTx* pParent /*=NULL*/,並聲明ID:CDialog(CInputmr::IDD, pParent)和tx(pParent)
CInputmr::CInputmr(CTx* pParent /*=NULL*/)
: CDialog(CInputmr::IDD, pParent),tx(pParent)
{
if(Create(CInputmr::IDD,pParent))//創建
ShowWindow(SW_SHOW);//顯示窗口
//就可以使用 tx-> 了
}



常用網絡數據包報頭結構->以太網、ARP、IP、TCP、UDP、ICMP、DNS、UDP僞報頭***************************************

#pragma pack(1)
typedef struct ethdr //以太網包頭14字節
{
unsigned char destination_mac[6];//目標MAC 6字節
unsigned char source_mac[6];//源MAC 6字節
unsigned short type;//後面的協議類型2字節 爲0806表示後面跟的包爲ARP包
}ET_HEADER,*PETHDR;

typedef struct arphdr //arp協議28字節
{
unsigned short hard_tpye;//硬件類型2字節 通常爲01 (以太網地址)
unsigned short protocol;//協議類型2字節 通常爲80 (IP地址)
unsigned char hard_length;//硬件地址長度1字節 通常爲6
unsigned char protocol_length;//協議地址長度1字節 通常爲4 (IP協議)
unsigned short operation_type;//操作類型 1爲ARP請求,2爲ARP應答,3爲RARP請求,4爲RARP應答
unsigned char source_mac[6];//源物理地址
struct in_addr source_ip;//源IP地址
unsigned char destination_mac[6];//目的物理地址
struct in_addr destination_ip;//目的IP地址
}ARP_HEADER,*PARPHDR;


// IP Header -- RFC 791 IP數據報頭
typedef struct tagIPHDR
{
u_char VIHL; // Version and IHL 版本4bit = 4 和 首部長度4bit = 5
u_char TOS; // Type Of Service 服務類型 1字節
short TotLen; // Total Length 總長度2字節,包括數據和報頭
short ID; // Identification 標識符2字節
short FlagOff; // Flags and Fragment Offset 標誌 3bit 和分段偏移量 13bit
u_char TTL; // Time To Live 生存期1字節,爲經過路由器的總次數
u_char Protocol; // Protocol 協議類型1字節
u_short Checksum; // Checksum 首部(只是IP首部!!不然就錯了,過不了網關!!)校驗和2字節
struct in_addr source_ip; // Internet Address - Source 源IP地址
struct in_addr destination_ip; // Internet Address - Destination 目的IP地址
}IP_HEADER, *PIP_HEADER;

//TCP Header TCP數據報頭
typedef struct tcp_hdr
{
unsigned short source_port; //源端口
unsigned short destination_port; //目的端口
unsigned long index; //32位序號
unsigned long makesuer_index; //32位確認序號
unsigned short header_length_and_flags; //首部長度和標誌位
unsigned short window_size; //窗口大小
unsigned short checksum; //檢查和
unsigned short exigency_pointer; //緊急指針
}TCP_HEADER;

//UDP Header --UDP數據報頭

typedef struct udp_hdr
{
unsigned short source_port; //源端口
unsigned short destination_port; //目的端口
unsigned short length; //數據長度
unsigned short checksum; //帶數據!檢查和
} UDP_HEADER;


// ICMP Header - RFC 792 ICMP數據報頭
typedef struct tagICMPHDR
{
u_char Type; // Type 類型
u_char Code; // Code 代碼
u_short Checksum; // Checksum 校驗和
u_short ID; // Identification 標識符
u_short Seq; // Sequence 序列號
char Data; // Data 數據(依情況而定)
}ICMP_HEADER, *PICMP_HEADER;


// ICMP Echo Request ICMP 請求數據報
typedef struct tagECHOREQUEST
{
ICMPHDR icmpHdr;
DWORD dwTime;
char cData[32];
}IMCP_REQUEST, *PIMCP_REQUEST;


// ICMP Echo Reply ICMP 迴響數據報
typedef struct tagECHOREPLY
{
IPHDR ipHdr;
ECHOREQUEST echoRequest;
char cFiller[256];
}ICMP_REPLY, *ICMP_REPLY;


typedef struct dns //DNS數據報:
{
unsigned short id;//標識,通過它客戶端可以將DNS的請求與應答相匹配;
unsigned short flags;//標誌:[QR | opcode | AA| TC| RD| RA | zero | rcode ]
unsigned short quests;//問題數目;
unsigned short answers;//資源記錄數目;
unsigned short author;//授權資源記錄數目;
unsigned short addition;//額外資源記錄數目;
}DNS,*PDNS;
//在16位的標誌中:QR位判斷是查詢/響應報文,opcode區別查詢類型,AA判斷是否爲授權回答,TC判斷
//是否可截斷,RD判斷是否期望遞歸查詢,RA判斷是否爲可用遞歸,zero必須爲0,rcode爲返回碼字段。

typedef struct psd //僞報頭,用於計算UDP校驗和
{
unsigned int source_ip; //源IP
unsigned int destination_ip; //目的IP
char mbz; // 0
char protocol; //協議 UDP = 17
unsigned short udp_length; //UDP 長度
}PSD,*PPSD;

//DNS查詢數據報:
typedef struct query
{
unsigned short type; //查詢類型,大約有20個不同的類型
unsigned short classes; //查詢類,通常是A類既查詢IP地址。
}QUERY,*PQUERY;

//DNS響應數據報:
typedef struct response
{
unsigned short name; //查詢的域名
unsigned short type; //查詢類型
unsigned short classes; //類型碼
unsigned int ttl; //生存時間
unsigned short length; //資源數據長度
unsigned int addr; //資源數據
}RESPONSE,*PRESPONSE;

#pragma pack()


網絡編程部分源碼->校驗和、隱藏IP方法、取得本地MAC********************************

//注意!!!!!!
//IP的檢查和只是IP頭部的20個字節,不然過不了網關!!!!
//而TCP和UDP和檢查和是數據和頭部都包括!!
//在計算檢查和之前IP或UDP或TCP報頭中 所有的成員 必須被初始化,包括 checksum!!!


//爲了保證系統和機器的******兼容性******,在定義網絡結構體或共用體時要加上
#pragma pack(1)
#pragma pack()
//如:
#pragma pack(1)
typedef struct response
{
unsigned short name;
unsigned short type;
unsigned short classes;
unsigned int ttl;
unsigned short length;
unsigned int addr;
}RESPONSE,*PRESPONSE;
#pragma pack()
//sizeof(RESPONSE)==16,如果不加#pragma pack那麼sizeof(RESPONSE)==20

//局域網內相同網段下的IP地址,數據包直接發給該主機的MAC地址,不同網段下的,數據包發給網關,
//如:202.198.153.17->202.198.153.64 以太包目的地址爲202.198.153.64 的MAC地址
//如:202.198.153.17->202.198.159.139 以太包目的地址爲202.198.153.254(網關) 的MAC地址

//隱藏IP的方法************************************************************************

WSADATA wsd;
SOCKET s;
BOOL bOpt;
struct sockaddr_in remote;
USHORT *buf=NULL;
ECHOREQUEST icmpHdr;
int ret;
unsigned short iTotalSize,
iIPVersion,
iIPSize,
cksum = 0;

if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)//打開WSA網絡函數
{
MessageBox("WSAStartup() failed: ");
return ;
}

s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,0);//建立SOCKET,注意第二個一定爲SOCK_RAW
if (s == INVALID_SOCKET)
{
MessageBox("WSASocket() failed: ");
return ;
}
bOpt = TRUE;
//設置SOCKET屬性
ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));

if (ret == SOCKET_ERROR)
{
MessageBox("setsockopt(IP_HDRINCL) failed: %d/n");
return ;
}
//修改IP包的值
iTotalSize = sizeof(icmpHdr) ;

iIPVersion = 4;
iIPSize = sizeof(IP_HDR) / sizeof(unsigned long);

icmpHdr.ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize;
icmpHdr.ipHdr.ip_tos = 0;
icmpHdr.ipHdr.ip_totallength = htons(iTotalSize);
icmpHdr.ipHdr.ip_id = 0;
icmpHdr.ipHdr.ip_offset = 0;
icmpHdr.ipHdr.ip_ttl = 128;
icmpHdr.ipHdr.ip_protocol = 1; //ICMP
buf=(USHORT *)&icmpHdr;
icmpHdr.ipHdr.ip_checksum = checksum(buf,sizeof(IP_HDR));
icmpHdr.ipHdr.ip_srcaddr = inet_addr(m_source_ip);
icmpHdr.ipHdr.ip_destaddr = inet_addr(m_destinition);

icmpHdr.icmpHdr.Type=8;
icmpHdr.icmpHdr.Code=0;
icmpHdr.icmpHdr.ID=1;
icmpHdr.icmpHdr.Seq=1;
buf=(USHORT *)&icmpHdr;
icmpHdr.icmpHdr.Checksum=checksum(buf+sizeof(IP_HDR),sizeof(icmpHdr)-sizeof(IP_HDR));
icmpHdr.dwTime=GetTickCount();

remote.sin_family = AF_INET;
remote.sin_port = 0;
remote.sin_addr.s_addr = inet_addr(m_destinition);

struct timeval Timeout;
fd_set readfds;

readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;
int nRet;
int nAddrLen = sizeof(struct sockaddr_in);
ECHOREPLY echoReply;

CString cs;

for(int i=0;i<m_ping_times;i++)
{ //發送IP包
ret = sendto(s, (char *)&icmpHdr, iTotalSize, 0, (SOCKADDR *)&remote, sizeof(remote));
if (ret == SOCKET_ERROR)
MessageBox("sendto() failed:");
/*
select(1, &readfds, NULL, NULL, &Timeout);

//接收請求迴應
nRet = recvfrom(s,
(LPSTR)&echoReply,
sizeof(ECHOREPLY),
0,
(LPSOCKADDR)&remote,
&nAddrLen);

//檢查返回值
if (nRet == SOCKET_ERROR)
MessageBox("recvfrom()");
cs.Format("%d",echoReply.ipHdr.ip_ttl);
MessageBox(cs);
//返回發送的時間
*/
Sleep(m_separete);
}

closesocket(s) ;
WSACleanup() ;//關閉WSA

}

//校驗和程序*****************************************************************************

USHORT CFffDlg::checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;

while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);

return (USHORT)(~cksum);
}

//取得本地機器IP地址*********************************************************************************************

WORD wv=MAKEWORD(1,1);
WSADATA ws;
WSAStartup(wv,&ws);
char name[256];
gethostname(name,256);
HOSTENT *hos=gethostbyname(name);
CString cs;
for(int i=0;hos!=NULL&&hos->h_addr_list[i]!=NULL;i++)
{
cs=inet_ntoa(*(struct in_addr*)hos->h_addr_list[i]);
MessageBox(cs);

}
WSACleanup();

//取得本地MAC地址*********************************************************************************************
#include <lm.h>
NetApi32.lib
unsigned char macdata[8];
WKSTA_TRANSPORT_INFO_0 * pwkti;
DWORD dwe,dwt;
BYTE *pb;
NET_API_STATUS dws=NetWkstaTransportEnum(
NULL,
0,
&pb,
MAX_PREFERRED_LENGTH,
&dwe,
&dwt,
NULL);
pwkti=(WKSTA_TRANSPORT_INFO_0 *)pb;
CString cs;
for(DWORD i=1;i<dwe;i++)
{
swscanf((wchar_t *)pwkti[i].wkti0_transport_address,L"%2hx%2hx%2hx%2hx%2hx%2hx",&macdata[0],
&macdata[1],&macdata[2],&macdata[3],&macdata[4],&macdata[5]);
cs.Format("%02x%02x%02x%02x%02x%02x",macdata[0],
macdata[1],macdata[2],macdata[3],macdata[4],macdata[5]);
MessageBox(cs);
}
NetApiBufferFree(pb);
//ADO連接代碼**************************************************************
//用#import引用msado15.dll。可以直接在Stdafx.h文件中加入
#import "c:/program files/common files/system/ado/msado15.dll" /
no_namespace /
rename ("EOF", "adoEOF")

// 定義ADO連接、命令、記錄集變量指針
_ConnectionPtr m_pConnection;
_CommandPtr m_pCommand;
_RecordsetPtr m_pRecordset;

//初始化連接
AfxOleInit();
m_pConnection.CreateInstance(__uuidof(Connection));
m_pRecordset.CreateInstance(__uuidof(Recordset));

// 在ADO操作語句中要常用try...catch()來捕獲錯誤信息,
// 因爲它會經常出現一些意想不到的錯誤。
try //打開庫
{
// 打開本地Access庫Demo.mdb
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Demo.mdb","","",adModeUnknown);
}
catch(_com_error e)
{
AfxMessageBox("數據庫連接失敗,確認數據庫Demo.mdb是否在當前路徑下!");
return FALSE;
}
try //打開表
{
m_pRecordset->Open("Select * FROM DemoTable", // 查詢DemoTable表中所有字段
m_pConnection.GetInterfacePtr(), // 獲取庫接庫的IDispatch指針
adOpenDynamic,
adLockOptimistic,
adCmdText);
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
//m_CListBox.AddString((LPCSTR)_bstr_t(m_pRecordset->GetCollect("Name")));//獲得Name字段的值
//m_pRecordset->PutCollect("Name", _variant_t(m_Name)); // 寫入各字段值


第一部分:記錄集


記錄集是從數據庫中按一定查詢條件讀入到內存中的一批記錄,以供快速的操作。
記錄集recordset對象的屬性,方法:
BOF:當記錄集記錄指針指到起始記錄(第1條記錄)再向前移(即超過第1條記錄),這時返回true.常用來對付一些出錯情況。注:在BOF或EOF時使用update方法會出錯。
EOF:當記錄指針指到最後一條記錄之後(即超過了最後1條記錄)時,該屬性返回true.注:當一個記錄集爲空時,其BOF和EOF屬性都爲True,可據此檢測一個記錄集是否爲空。
AbsolutePosition:返回當前記錄指針,即當前記錄是第幾條記錄,只讀。
BookMark: 設置/返回當前記錄指針的書籤,爲字符串。如:
在當前記錄處設置書籤:lxn=Adodc1.Recordset.BookMark
當指針移動後回到指定書籤位置:Adodc1.Recordset.BookMark=lxn.
返回記錄集中記錄的總數:RecordCount屬性。該屬性對於表形式的記錄集將返回精確數目,但對於僅向前型記錄集(adOpenForwardOnly),返回-1。動態記錄集(adOpenDynamic)則不一定,可能返回-1,與記錄集的CursorLocation有關;而對於靜態記錄集(adOpenStatic),也總能返回精確數目。附:在DAO中,對動態集和快照集需要先用MoveFirst和Movelast方法,再用RecordCount取得記錄精確數目。
Move方法:移動記錄集指針。該方法有兩個參數,第一個參數指定要向前或向後移動多少條記錄,第二個參數指定一個相對書籤位置,表明從當前記錄還是從第1條或最後1條記錄開始算,缺省爲0從當前記錄開始移,將指針從當前位置向前(負數)或向後(正數)移動指定條記錄(第二個‘按書籤移動’參數設爲0-adBookMarkCurrent從當前記錄開始,缺省)或將指針從第1條記錄算起移動指定條記錄(第二個參數設爲1-adBookMarkFirst從首記錄)。或將指針從最後1條記錄算起移動指定條記錄(第二個參數設爲adBookMarkLast),如:Adodc1.Recordset.Move -12,將指針從當前位置向前移動12條記錄,再如Adodc1.Recordset.Move 6 , 1表示指針從首記錄開始後移6條記錄,即使指針移到第7條記錄。Move方法有幾個引申的方法,如下:
movefirst,記錄集指針移到第1條記錄;
movelast,記錄集指針移到最後1條記錄;
moveprevious,記錄集指針移到上一條記錄;
movenext,記錄集指針移到下一條記錄。
Find方法:查找滿足條件的記錄。
find方法簡略格式爲:
adodc對象.recordset.find 查找表達式(爲“字段 比較符號 值”)
其他參數採用缺省,find工作方式是:從當前記錄指針位置開始(含當前記錄)向後逐條檢索記錄,遇到滿足條件的1條記錄就停下來,指針指到此記錄。
因此,若要實現“繼續尋找下1個”的功能,只要將記錄指針移到下1條記錄(用movenext一下),再照原樣使用find即可。 而重新查找必須先用movefirst將指針指到開頭。
Adodc1.Recordset.find "姓名 = '李長春'"
其中查找表達式的樣子爲“字段 比較符號 值”,比較符號不僅可以是等號,還可以是>,<,<=,>=,<>,like等。其中Like和 = 很相近,只不過like專用於字符串比較,不區分字母的大小寫可用通配符,而 = 號會區分字母大小寫不能用通配符。
一般情況下,查找表達式常採用變量表示,由用戶來確定,如下:
Dim lxn As String
Static a As String
a = InputBox("請輸入查找姓名","查找")
lxn = "NAME like '" & a & "'"
.Find lxn

LockType屬性:設置記錄集中的記錄鎖定方式,是否可修改及修改方式:有1-adLockReadOnly(只讀);2-adLockPessimistic(保守式修改),當修改記錄後立即將更改保存到數據源,3-adLockOptimistic(開放式修改),當修改記錄後只有調用Update方法纔將更改保存到數據源;4-adLockBatchOptimistic(開放式批處理修改)。當修改記錄後只有調用UpdateBatch方法纔將更改保存到數據源。對於ADO對象而言,該屬性的缺省值爲1-adLockReadOnly只讀,要編輯記錄則必須加以改變。
Update方法:對記錄集當前記錄的更改進行保存到數據庫。
UpdateBatch方法:成批保存更改的多條記錄。只有當記錄集使用鎖定方式爲adLockBatchOptimistic打開時該方法纔有效。使用該方法,可以加快更新速度。因爲一條一條更新的話,速度慢,而多條一起更新的話,其實等同於一個更新操作,因此更快。該方法有個可選參數AffectRecords提一下,它可設爲:adAffectCurrent只更新當前記錄;adAffectGroup只更新當前Filter屬性滿足的記錄;adAffectAll(缺省)全部更新,包括被當前Filter屬性隱藏的記錄。
CancelUpdate方法:放棄保存對當前記錄自上次Update後的更改,即不保存當前所作的修改。通常在WillChangeRecord事件中進行數據驗證時用。當然一般是直接將事件提供的參數adStatus設爲adStatusCancel即可取消保存。這裏要注意,在WillChangeRecord事件中取消一個操作,將發生“操作已取消”的錯誤。照我的感覺,還不如直接在要Update的代碼前面去驗證輸入的數據。
在記錄集中添加新記錄,用addnew方法先在緩存中添加一個新的空記錄,這時它自動成爲當前記錄,通過修改,然後用update方法保存,data1.recordset.update,說明:如果用Movenext等方法將記錄指針移開時記錄集會自動保存緩存中的記錄(等於調用Update方法)。
修改當前記錄,只要直接給字段賦值就可以了,注意賦值後也要用Update方法將緩存中的數據保存,否則不會自動更新,除非用MoveNext等方法將指針移開讓它自動調用。
刪除當前記錄用Delete方法就行了。有一點要注意,刪除後,記錄指針仍在被刪除的記錄上,因此要用MoveNext等方法將指針移開,或乾脆Requery刷新一下。
Sort:指定用來對全部記錄排序的參照字段。
Fields:包含記錄集中各字段的集合。指定某個字段格式爲:fields("字段名")。可省略。如有:m$=data1.recordset.fields("姓名").value爲讀當前記錄(用value表示)的“姓名”字段值。還可用來在代碼中修改(寫)記錄值(不是用綁定控件),如修改記錄值爲“李新能”:data1.recordset.fields("姓名").value="李新能"。也可寫爲data1.recordset("姓名").value,括號內寫明字段名或“字段索引值”,第1個字段索引值從0開始。如data1.recordset(0).value.
關閉記錄集用close方法,格式爲“記錄集.close”。
要讀或寫當前記錄的某個字段值,只要用“記錄集("字段名")”就可以了,Fields和Value都是缺省屬性,但當值是一個記錄集的除外,如數據環境中Command命令對象的子命令對象。
刷新記錄集(即重新打開記錄集):Requery方法。在記錄集打開的情況下,迅速關閉又打開一次,以達到確保記錄集始終處於激活狀態。
返回/設置記錄集當前編輯狀態:EditMode屬性。有以下三個可能返回值:adEditNone沒有編輯;adEditInProgress正在編輯(即當前記錄已修改但未保存);adEditAdd已經用AddNew方法添加新記錄但還未存盤,在緩存中的是新記錄。這個屬性通常用來檢測某些操作狀態,比如可在窗體的Unload事件中防止修改了的記錄未保存就卸載。
★ AbsolutePage屬性:指定當前記錄所在的頁。其值的範圍在1—PageCount值之間,所謂頁,是把Recordset對象按PageSize爲標準分爲若干頁面,每一頁(除最後一頁)記錄數相等(等於PageSize)。有三個特殊值:adPosUnkown未知位置;adPosBOF在文件頭;adPosEOF在文件尾。
★ ActiveCommand:屬性:只讀屬性。返回關聯的Command對象,如果記錄集不是由Command對象創建的,則返回Null.
★ ActiveConnection屬性:設置/返回記錄集基於哪個Connection對象,如果沒有Connection對象,則直接指定一個連接字符串。
★ Cancel: 取消執行異步 Execute(對Connection和Command對象而言) 或 異步Open 方法調用(即通過 adAsyncConnect、adAsyncExecute 或 adAsyncFetch 參數選項調用這些方法)。
★ CacheSize屬性:本地內存緩存的大小。
★ CancelBatch方法: 取消批更新模式下記錄集中所有還未執行的更新。
★ Clone方法:複製一個記錄集。格式:Set 記錄集變量=記錄集.Clone [adLockReadOnly]當指定可選參數adLockReadOnly表示創建只讀的記錄集副本。使用 Clone 方法可創建多個 Recordset 對象副本,這對於希望在給定的記錄組中保留多個當前記錄十分有用。使用 Clone 方法比使用與初始定義相同的定義創建和打開新 Recordset 對象要有效得多。新創建副本的當前記錄將設置爲首記錄。無論遊標類型如何,對某個 Recordset 對象所作的修改在其所有副本中都是可見的。不過一旦在原始 Recordset 上執行了 Requery,副本將不再與原始 Recordset 同步。關閉原始 Recordset 時並不關閉它的副本,而關閉某個副本也將不關閉原始 Recordset 或任何其他副本。用戶只允許複製支持書籤的 Recordset 對象。書籤值是可交換的,也就是說,來自一個 Recordset 對象的書籤引用可引用其任何副本中的相同記錄。
★ CompareBookmarks: 比較兩個書籤並返回它們相差值的說明。即誰先誰後。
★ CursorLocation: 設置或返回遊標服務的位置。遊標:可以簡單理解爲指向若干行的指針。有三種設置值:adUseNone 沒有使用遊標服務。(該常量已過時並且只爲了向後兼容纔出現,通常不用)。adUseClient 使用由本地遊標庫提供的客戶端遊標,通常使用這種遊標。adUseServer 使用數據提供者的或驅動程序提供的遊標。
該屬性應在建立連接之前設置,更改 CursorLocation 屬性不會影響現有的連接。
遠程數據服務用法 當用於客戶端 (ADOR) Recordset 或 Connection 對象時,只能將 CursorLocation 屬性設置爲 adUseClient。
★ CursorType: 指示在 Recordset 對象中使用的遊標類型。AdOpenForwardOnly 僅向前遊標,默認值。除了只能在記錄中向前滾動外,與靜態遊標相同。當只需要在記錄集中單向移動時,使用它可提高性能。
AdOpenKeyset 鍵集遊標。儘管從您的記錄集不能訪問其他用戶刪除的記錄,但除無法查看其他用戶添加的記錄外,鍵集遊標與動態遊標相似。仍然可以看見其他用戶更改的數據。
AdOpenDynamic 動態遊標。可以看見其他用戶所作的添加、更改和刪除。允許在記錄集中進行所有類型的移動,但不包括提供者不支持的書籤操作。
AdOpenStatic 靜態遊標。可以用來查找數據或生成報告的記錄集合的靜態副本。另外,對其他用戶所作的添加、更改或刪除不可見。
說明:使用 CursorType 屬性可指定打開 Recordset 對象時應該使用的遊標類型。Recordset 關閉時 CursorType 屬性爲讀/寫,而 Recordset 打開時該屬性爲只讀。
如果將 CursorLocation 屬性設置爲 adUseClient 則只支持 adOpenStatic 的設置。
★ Filter屬性:過濾器。對記錄集進行篩選,返回記錄集中滿足條件的所有記錄,該屬性指定一個篩選字符串,爲一個“字段-比較符號-值”的條件表達式,當該屬性賦值後,記錄集立即變成篩選後的方式,包括如 AbsolutePosition、AbsolutePage、RecordCount 和 PageCount等屬性都將改變,“變”成了一個“新”記錄子集,當前記錄移動到記錄子集的第一個記錄。而當清除 Filter 屬性後,記錄集立即恢復,當前記錄位置將移動到原Recordset 的第一個記錄。
關於“字段-比較符號-值”的說明:“字段” 必須爲 Recordset 中的有效字段名。如果字段名包含空格,必須用方括號將字段名括起來。
“比較符號”必須使用的操作符爲:<、>、<=、>=、<>、= 或 LIKE。
“值” 是用於與字段值(如 'Smith'、#8/24/95#、12.345 或 $50.00)進行比較的值。字符串使用單引號而日期使用井號 #(注:在SQL中不用#號),對於數字,可以使用小數點、貨幣符號和科學記數法。如果 “比較符號” 爲 LIKE,“值” 則可使用通配符。ADO和SQL只允許使用下劃線(_) 和百分號 (%) 通配符,而且必須爲字符串的尾字符。DAO只允許使用問號(?)和星號(*)作通配符.“值” 不可爲 Null。在 LIKE 子句中,可在樣式的開頭和結尾使用通配符(如 LastName Like '*mit*'),或者只在結尾使用通配符(如,LastName Like 'Smit*')
Filter屬性還有幾個特殊值可供選擇:AdFilterNone 刪除當前篩選條件並恢復查看所有記錄。同空字符串””。 AdFilterPendingRecords 允許只查看已更改且尚未發送到服務器的記錄。只能應用於批更新模式。 AdFilterAffectedRecords 允許只查看上一次 Delete、Resync、UpdateBatch 或 CancelBatch 調用所影響的記錄。 AdFilterFetchedRecords 允許查看當前緩衝區中的記錄,即上一次從數據庫中檢索記錄的調用結果。 AdFilterConflictingRecords 允許查看在上一次批更新中失敗的記錄。
★ GetRows方法: 將Recordset的多個記錄值複製到數組中,應當先定義一個變體變量,然後將GetRows的返回值賦給它,這個變量就成了一個二維數組,其第一維下標標識原所在的列(字段),第二維下標標識原所在的行(記錄),每一個交叉點就是一個值了,如:
Dim VariData As Variant
VariData = DataEnvironment1.rsCommand1.GetRows
x = UBound(VariData, 1)
y = UBound(VariData, 2)
For m = 0 To x
For n = 0 To y
Print VariData(m, n); ‘用分號表示同一字段的數據打印在同一行。
Next n
Print
Next m
該方法格式:變體變量=記錄集.GetRows([rows],[start],[fields])有三個可選參數,第一個參數Rows限制返回的記錄數量,即要複製幾行記錄,它決定的是變體數組的第二維長度,缺省情況下,將讀取記錄集中的所有記錄。第二個參數Start指定從哪個記錄位置開始向數組複製記錄,可以是一個記錄書籤字符串,或以下三個常數之一:adBookMarkCurrent(當前記錄)adBookMarkFirst(首記錄錄)adBookMarkLast(尾記錄);第三個參數Fields限制返回的記錄字段,即要複製哪幾列,它決定的是變體數組的第一維長度,缺省情況下,將讀取記錄集中的所有字段,該參數可設置爲單個字段名字符串,或多個字段名字符串組成的數組。
注意:使用該方法複製記錄值時,記錄指針將隨之移動,每複製一行後,指針自動移動到下一行。
★ GetString: 將 Recordset 按字符串值的變體型 (BSTR) 返回。
★ MarshalOptions: 彙集選項。指示要被調度返回服務器的記錄。可選設置值:AdMarshalAll 默認值。表明所有行將返回到服務器。 AdMarshalModifiedOnly 表明只有已修改的行返回到服務器。當使用客戶端 (ADOR) Recordset 時,已在客戶端被修改的記錄將通過稱作“調度”的技術寫回中間層或 Web 服務器。
★ MaxRecords: 指示通過一次查詢返回 Recordset 的記錄的最大數目。使用 MaxRecords 屬性可對從數據源返回的記錄數加以限制。該屬性的默認設置爲零,表明提供者返回所有所需的記錄。Recordset 關閉時,MaxRecords 屬性爲讀/寫,打開時爲只讀。
★ NextRecordset:清除當前Recordset對象,執行下一個命令返回新的Recordset對象。當一個命令語句是複合語句(即用分號隔開的多條命令)?時,用該方法依次執行下一條命令。格式:Set recordset2=recordset1.NextRecordset。例如:
Dim rst As ADODB.Recordset
Dim strCnn As String
Dim strCmd As String
strCnn = "Provider=Microsoft.Jet.OLEDB.3.51;Persist Security Info=False;Data Source=C:/工商所收費系統/MyDatabase.mdb"
strCmd = "Select * FROM unitrecord;Select * FROM invoice" ‘AccessSQL不支持。
Set rst = New ADODB.Recordset
rst.Open strCmd, strCnn, adOpenDynamic, adLockOptimistic, adCmdText
Print rst("Name")
Set rst = rst.NextRecordset
Print rst("Name")
rst.Close
★ Open:打開一個遊標,即記錄集。
★ PageCount:頁面數。
★ PageSize:每頁大小,缺省爲10。
★ Properties:
★ Resync:
★ Save:
★ Seek方法:使用索引進行查詢,比用Find方法速度更快,但只能用於以表形式打開的記錄集,不能用於動態記錄集或快照型記錄集,不能在遠程服務器表上使用Seek,因爲遠程數據源不能以表形式打開。而且這個表預先定義了索引字段,使用Seek方法前,要在代碼中用Index屬性指定當前要使用的索引,格式爲:記錄集對象.Index=索引名。索引名是在表的設計階段定義好的。注意索引名不等於字段名,只不過是以某個字段爲標準的。設置好要使用的索引後,使用Seek進行查找,格式:Recordset對象.Seek 值,這裏的值參數指定按當前索引所屬字段進行查找的值,若找到,則指針指到此記錄,若沒找到,則EOF爲True.
一般情況下,在ADO中都不用Seek進行定位,而是用SQL查詢生成動態記錄集。只是在DAO中有一些使用,如:
Private Sub Command2_Click()
Data1.Recordset.Index = "indexName"
Data1.Recordset.Seek "=", "李春生"
Text1.Text = Data1.Recordset(2)
End Sub
其格式有一點不同,它的第一參數指定一個比較符號,第二個參數纔是值,需要在屬性窗口中將DATA1的RecordsetType屬性設置爲0-Table。
★ Sort:
★ Source:數據源。
★ State:對象的當前狀態,有adStateClosed(關閉)或adStateOpen(打開)。
★ Status:批量操作或海量操作的狀態。
★ StayInSync:
★ Supports方法:判斷本記錄集是否具有某個方面的功能。如:是否允許增添記錄If rst.Supports(adAddnew)=True then rst.Addnew,如果具有某項功能則返回True,不具備則返回False,該方法的一個參數是指定哪個方面,如adDelete是否允許刪除記錄,adBookmark是否支持書籤設置,adUpdate是否允許更新(即修改)數據源,adIndex是否可以使用index屬性設置索引,adSeek是否可用Seek方法定位記錄指針。再如判斷是否支持索引:MsgBox DataEnvironment1.rsCommand1.Supports(adIndex)。
記錄集有五種不同的類型:
Table:表示數據庫中一張表,記錄集與數據庫中的數據同步,可通過記錄集對數據庫添加,刪除等操作。
Dynaset:一張查詢結果集,可由多個表中不同數據組成,可通過記錄集對數據庫進行添加、刪除等操作。
Dynamic:與dynaset相似,但它有這樣的功能:當其他用戶修改記錄集的基表(數據庫表)時,會將修改反映到這個記錄集中,主要用於多用戶操作。
SnapShot:一張只讀的查詢結果集,可包含不同表中數據記錄,不能對記錄添加,修改等,可用於瀏覽數據庫。
Forward-Only:一個沒遊標的SnapShot記錄集,只能從頭到尾順序經過所有記錄,不能任意移動。

//ODBC動態創建數據源*********************************************************

#define ODBC_ADD_DSN 1 // Add data source
#define ODBC_CONFIG_DSN 2 // Configure (edit) data source
#define ODBC_REMOVE_DSN 3 // Remove data source
#include <odbcinst.h>

CString sPath;
GetModuleFileName(NULL,sPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
sPath.ReleaseBuffer ();
int nPos;
nPos=sPath.ReverseFind ('//');
sPath=sPath.Left (nPos);
nPos=sPath.ReverseFind('//');
sPath=sPath.Left (nPos);
CString lpszFile = sPath + "//DataBase.mdb";


char* szDesc;
int mlen;
szDesc=new char[256];
sprintf(szDesc,"DSN=%s? DESCRIPTION=TOC support source? DBQ=%s? FIL=MicrosoftAccess? DEFAULTDIR=%s?? ","zth",lpszFile,sPath);



mlen = strlen(szDesc);
for (int i=0; i<mlen; i++)
{
if (szDesc[i] == '?')
szDesc[i] = '/0';
}

if (FALSE == SQLConfigDataSource(NULL,ODBC_ADD_DSN,"Microsoft Access Driver (*.mdb)/0",(LPCSTR)szDesc))
AfxMessageBox("SQLConfigDataSource Failed");

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章