青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

xbgs

C++博客 首頁 新隨筆 聯系 聚合 管理
  7 Posts :: 0 Stories :: 13 Comments :: 0 Trackbacks

2008年12月17日 #

    消息映射、循環機制是Windows程序運行的基本方式。VC++ MFC 中有許多現成的消息句柄,可當我們需要完成其它的任務,需要自定義消息,就遇到了一些困難。
    在MFC ClassWizard中不允許添加用戶自定義消息,所以我們必須在程序中添加相應代碼,以便可以象處理其它消息一樣處理自定義消息。通常的做法是采取以下步驟:
第一步:定義消息。
 推薦用戶自定義消息至少是WM_USER+100,因為很多新控件也要使用WM_USER消息。
#define WM_MY_MESSAGE (WM_USER+100) 
第二步:實現消息處理函數。
該函數使用WPRAM和LPARAM參數并返回LPESULT。
LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
    // TODO: 處理用戶自定義消息
    ...
    return 0;

第三步:在類頭文件的AFX_MSG塊中說明消息處理函數:
class CMainFrame:public CMDIFrameWnd
{
    ...
    // 一般消息映射函數
    protected:
    // {{AFX_MSG(CMainFrame)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnTimer(UINT nIDEvent);
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
}
第四步:在用戶類的消息塊中,使用ON_MESSAGE宏指令將消息映射到消息處理函數中。
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
    ON_WM_CREATE()
    ON_WM_TIMER()
    ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

 
  如果用戶需要一個定義整個系統唯一的消息,可以調用SDK函數RegisterWindowMessage定義消息:
static UINT WM_MY_MESSAGE=RegisterWindowMessage("User");

  并使用ON_REGISTERED_MESSAGE宏指令取代ON_MESSAGE宏指令,其余步驟同上。
  當需要使用自定義消息時,可以在相應類中的函數中調用函數PostMessage或SendMessage發送消息PoseMessage(WM_MY_MESSAGE,O,O);
如果向其他進程發送消息可通過如下方法發送消息:
DWORD result;
SendMessageTimeout(wnd->m_hWnd, // 目標窗口
                   WM_MY_MESSAGE, // 消息
                   0, // WPARAM
                   0, // LPARAM
                   SMTO_ABORTIFHUNG |
                   SMTO_NORMAL,
                   TIMEOUT_INTERVAL,
                   &result);
以避免其它進程如果被阻塞而造成系統死等狀態。
    可是如果需要向其它類 (如主框架、子窗口、視類、對話框、狀態條、工具條或其他控件等 發送消息時上述方法顯得無能為力,而在編程過程中往往需要獲取其它類中的某個識別信號 框架給我們造成了種種限制,但是可以通過獲取某個類的指針而向這個類發送消息, 而自定義消息的各種動作則在這個類中定義,這樣就可以自由自在的向其它類發送消息了。 


  下面舉的例子敘述了向視類和框架類發送消息的方法:
★在主框架類中向視類發送消息:
1.視類中定義消息:
ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //定義消息映射

2.視類定義消息處理函數:
LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
    // TODO: 處理用戶自定義消息
    ...
    return 0;
}
3.發送消息的測試函數
void CMainFrame::OnTest()
{
    CView * active = GetActiveView();//獲取當前視類指針
    if(active != NULL)
    active->PostMessage(WM_MY_MESSAGE,0,0);
}
★在其它類中向視類發送消息:
//發送消息的測試函數
void CMyDialog::OnTest()
{
    CMDIFrameWnd *pFrame;
    CMDIChildWnd *pChild;
    CView *pView;
    //獲取主窗口指針
    pFrame =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
    // 獲取子窗口指針
    pChild = (CMDIChildWnd *) pFrame->GetActiveFrame();
    //獲取視類指針
    pView = pChild->GetActiveView();
    if(pView != NULL)
    pView->PostMessage(WM_MY_MESSAGE,0,0);//發送消息
}
其余步驟同上。
★在視類中向主框架發送消息:
首先在主框架中定義相關的消息,方法同上,然后在發送消息的函數中添加代碼如下
//發送消息的測試函數
void CMessageView::OnTest()
{
    CFrameWnd * active = GetActiveFrame();//獲取當前主窗口框架指針
    if(active != this)
    active->PostMessage(WM_MY_MESSAGE,0,0);
    return 0;
}
  在其它類中向不同的類發送消息可依次方法類推,這樣我們的程序就可以的不受限制向其它類和進程發送消息,而避免了種種意想不到的風險。
 
【實例】:
  下面一個例子程序為多文檔程序里在一對話框中向視類發送消息,詳述了發送自定義消息的具體過程。
  實現步驟:

第一步:在VC++中新建工程Message,所有ClassWizard步驟選項均為缺省,完成。
第二步:在主菜單中添加測試菜單為調出對話框,在框架類中建立相應函數OnTest().
第三步:在資源中建立對話框,通過ClassWizard添加新類TestDialog,添加測試按鈕, 在對話框類中建立相應函數OnDialogTest()
//通過對話框按鈕發送消息的函數
void TestDialog::OnDialogTest()
{
    CMDIFrameWnd *pFrame;
    CMDIChildWnd *pChild;
    CView *pView;
    //獲取主窗口指針
    pFrame =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
    // 獲取子窗口指針
    pChild = (CMDIChildWnd *) pFrame->GetActiveFrame();
    //獲取視類指針
    pView = pChild->GetActiveView();
    if(pView != NULL)
    pView ->PostMessage(WM_MY_MESSAGE,0,0);//發送消息
}
  在Message.h頭文件中添加如下語句:
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
第四步:在視類中添加自定義消息:
在頭文件MessageView.h中添加消息映射
protected:
//{{AFX_MSG(CMessageView)
//}}AFX_MSG
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); //此行為添加代碼
DECLARE_MESSAGE_MAP()
在視類文件MessageView.cpp中的消息映射中添加自定義消息映射
BEGIN_MESSAGE_MAP(CMessageView, CView)
//{{AFX_MSG_MAP(CMessageView)
//}}AFX_MSG_MAP
// Standard printing commands
ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //此行添加代碼定義唯一消息
END_MESSAGE_MAP()
添加相應的0消息處理函數
LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
    CRect rect;
    GetClientRect(&rect);
    InvalidateRect(&rect);
    test=!test;
    return 0;
}
在MessageView.h中添加布爾變量 public:BOOL test;
在視類構造函數中初始化 test變量:test=FALSE;
修改CMessageView::OnDraw()函數
void CMessageView::OnDraw(CDC* pDC)
{
    CMessageDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // 以下程序顯示消息響應效果
    if(test)
    pDC->TextOut(0,0,"消息響應!");
}
第五步:顯示測試對話框
在MainFrame類中包含對話框頭文件:
#include "TestDialog.h";
OnTest()函數中添加代碼
void CMainFrame::OnTest()
{
    TestDialog dialog;
    dialog.DoModal();
}
運行程序,在測試菜單打開對話框,點擊測試按鈕即可看到結果
posted @ 2008-12-17 13:18 讓心飛翔 閱讀(1589) | 評論 (0)編輯 收藏

2006年6月23日 #

很多人都覺得自己的程序的界面不那么美觀,往往VC默認產生的對話框比較單調,因此很多人往往找到很多其它的控件對對話框進行美化修飾,例如給靜態控件設置字體,設置背景顏色等等, 其實這些完全可以由VC自己的WM_CTLCOLOR消息來完成!

WM_CTLCOLOR消息用來完成對EDIT、STATIC、BUTTON等控件設置背景和字體顏色,其用法如下:

1.首先在自己需要設置界面的對話框上點擊右鍵-->建立類向導-->加入WM_CTLCOLOR消息-->自動生成OnCtlColor()函數,此函數可以對本對話框的控件的界面外觀做修飾,用法如下:
將類向導產生的函數做如下修改:

HBRUSH CDialogColor::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
HBRUSH hbr = CDialog::OnCtlColor(pDC,pWnd, nCtlColor);
// TODO: Change any attributes of theDC here
//設置顯示字體
CFont * cFont=new CFont;
cFont->CreateFont(16,0,0,0,FW_SEMIBOLD,FALSE,FALSE,0,
ANSI_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
DEFAULT_PITCH&FF_SWISS,"Arial");
//對特定的控件做修改
switch()
{
case CTLCOLOR_STATIC: //對所有靜態文本控件的設置
{
pDC->SetBkMode(TRANSPARENT);
//設置背景為透明
pDC->SetTextColor(RGB(255,255,0)); //設置字體顏色
pWnd->SetFont(cFont); //設置字體
HBRUSH B = CreateSolidBrush(RGB(125,125,255));
//創建畫刷
return (HBRUSH) B; //返回畫刷句柄
}
case CTLCOLOR_EDIT: //對所有編輯框的設置
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,255,0));
pWnd->SetFont(cFont);
HBRUSH B = CreateSolidBrush(RGB(125,125,255));
return (HBRUSH) B;
}
default:
return CDialog::OnCtlColor(pDC,pWnd, nCtlColor);
}
}

注:case的類別有以下幾種:
CTLCOLOR_BTN 按鈕控件
CTLCOLOR_DLG 對話框
CTLCOLOR_EDIT 編輯框
CTLCOLOR_LISTBOX 列表框
CTLCOLOR_MSGBOX 消息框
CTLCOLOR_SCROLLBAR 滾動條
CTLCOLOR_STATIC 靜態文本

2.你可能覺得對所有的控件使用統一的界面設置覺得不自由,其實VC同樣可以對特定的ID的控件進行設置,方法如下:


switch (pWnd->GetDlgCtrlID())
{
//針對ID為IDC_CTL1、IDC_CTL2和IDC_CTL3的控件進行同樣的設置
case IDC_CTL1:
case IDC_CTL2:
case IDC_CTL3:
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,255, 0));
pWnd->SetFont(cFont);
HBRUSH B = CreateSolidBrush(RGB(125,125,255));
return (HBRUSH) B;
}
default:
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}
posted @ 2006-06-23 23:21 讓心飛翔 閱讀(6995) | 評論 (1)編輯 收藏

??? 在對話框程序的打印功能中,如果使用針式打印機,那么你可能希望連續打印的多個表中不換頁。我們知道,在使用打印功能的時候,每當 dc.startpage()就會開始一頁的打印,而dc.endpage()就會結束一頁的打印,那么如何能使多個dc.startpage()與 dc.endpage()不換頁而實現連續打印呢,方法如下: 假設我們要打印m_nTotalNum個表,每個表有m行,那么要實現m_nTotalNum個表連續打印不換頁可以如下實現:(由于打印機制問題,在打滿一張后是必須要換頁的,我們的做法是在換頁的地方讓給它留出一定的空白,不太影響表的連續性)
/////////////主函數
void CDlgTest::PrintOneNum() 
{
CDC dc;
CPrintDialog printDlg(FALSE);
CPrintInfo Info;
printDlg.GetDefaults();
dc.Attach(printDlg.GetPrinterDC());
dc.m_bPrinting=TRUE;
CString strTitle;
strTitle.LoadString(AFX_IDS_APP_TITLE);
DOCINFO di;
::ZeroMemory(&di,sizeof(DOCINFO));
di.cbSize=sizeof(DOCINFO);
di.lpszDocName=strTitle;
if(dc.m_hDC)
{
BOOL bPrintingOk=dc.StartDoc(&di);
CPrintInfo Info;
m_nCurrentNum_WhenPrint=1; //當前表數為1,這個用來控制打印的表數
int nPageTotalScale=0; //初始化從0開始
Info.m_nCurPage=1; //從第一頁開始
dc.StartPage(); //開始打印頁
for(;;)
{
//打印完需要的表數m_nTotalNum則退出循環
if(m_nCurrentNum_WhenPrint >m_nTotalNum) break;
else //打印一張表
{
nPageTotalScale=OnPrintReport (&dc,&Info,nPageTotalScale, m_nCurrentNum_WhenPrint);
m_nCurrentNum_WhenPrint ++;
nPageTotalScale+=30; //打印下一張表的行距從+30開始
}
}
bPrintingOk=(dc.EndPage()>0); //結束一頁
m_nCurrentNum_WhenPrint =0;
if(bPrintingOk)
dc.EndDoc();
else
dc.AbortDoc();
}
else
{
MessageBox("請檢查打印機是否連接完好?","我的程 序",MB_ICONEXCLAMATION);
}
dc.Detach();
}

/////////////打印函數
int CdlgTest::OnPrintReport(CDC *pDC, CPrintInfo *pInfo, 
int nXBasePointWhenPrint, int m_nCurrentNum_WhenPrint)
{
int nXCurrentPoint=nXBasePointWhenPrint; //進行行控制的變量
//--------換頁---------
if(nXCurrentPoint+210> 2000) //210為將要占用的長度
{
pDC->EndPage();
pDC->StartPage();
nXCurrentPoint=0;
pInfo->m_nCurPage++;
}
nXCurrentPoint+=210;
pDC->TextOut(0,nXCurrentPoint,"我的報表內容,從0-210的表長度 ");
//每當打印的輸出要換行的時候就要判斷if(nXCurrentPoint+將要使用的高度> 2000)2000為規定的一張紙的高度。 如果大于紙張高度就要換頁。這樣就保證打印內容連續。
return nXCurrentPoint; //最后返回打印完當前表時當前的頁面高度,
以便下一張表接著這個高度打印

}
posted @ 2006-06-23 23:18 讓心飛翔 閱讀(993) | 評論 (0)編輯 收藏

?在單文檔中的使用方法
步驟一 初始化

在CView類的.h頭文件中包含文件:
??? #include "Gridctrl.h"

并且手寫加入如下的成員函數:
????CGridCtrl * m_pGridCtrl;

步驟二 構造與析構

構造函數中:
???m_pGridCtrl = NULL;
析構函數中:
???if(m_pGridCtrl)
???????delete m_pGridCtrl;


步驟三 如果需要打印功能的話添加同名打印函數代碼

在CView類的OnBeginPrinting()函數中添加如下代碼:
if(m_pGridCtrl)
????m_pGridCtrl->OnBeginPrinting(pDC,pInfo);
//簡單吧,這就是類的好處

其它兩個打印函數也一樣的做法.

步驟四 在OnInitaUpdate()函數中或者你自己添加的要顯示Grid的消息函數中如下初始化:

   //創建非模式對話框
CDlg *dlg;
dlg=new CDlg();
dlg->Create(IDD_Dlg,this);

//初始化GridCtrl控件
if(m_pGridCtrl!=NULL)
{
delete m_pGridCtrl;
m_pGridCtrl=NULL;
}
if (m_pGridCtrl == NULL)
{
// Create the Gridctrl object
m_pGridCtrl = new CGridCtrl;
if (!m_pGridCtrl) return 0;
// Create the Gridctrl window
CRect rect;
GetClientRect(rect);
m_pGridCtrl->Create(rect, this, 100);
// fill it up with stuff
m_pGridCtrl->SetEditable(false);
m_pGridCtrl->SetTextBkColor(RGB(0xFF, 0xFF, 0xE0)); //黃色背景
m_pGridCtrl->EnableDragAndDrop(false);
try {
m_pGridCtrl->SetRowCount(k); //設置行數為k行
m_pGridCtrl->SetColumnCount(4); //k列
m_pGridCtrl->SetFixedRowCount(1); //標題行為一行
m_pGridCtrl->SetFixedColumnCount(1); //同上
}
catch (CMemoryException* e)
{
e->ReportError();
e->Delete();
return 0;
}
//填充列標題
int row=0;
for(int col=0;col<4;col++)
{
GV_ITEM Item;
Item.mask = GVIF_TEXT|GVIF_FORMAT;
Item.row = row;
Item.col = col;
if(col==0){
Item.nFormat = DT_CENTER|DT_WORDBREAK;
Item.strText.Format(_T("【類別】"),col);
}
else if(col==1){
Item.nFormat = DT_LEFT|DT_WORDBREAK;
Item.strText.Format(_T("第一列"),col);
}
else if(col==2){
Item.nFormat = DT_LEFT|DT_WORDBREAK;
Item.strText.Format(_T("第二列"),col);
}
m_pGridCtrl->SetItem(&Item);
}
// fill rows/cols with text
for (row = 1; row < k; row++)
for (col = 0; col < h; col++)
{
GV_ITEM Item;
Item.mask = GVIF_TEXT|GVIF_FORMAT;
Item.row = row;
Item.col = col;
if (col < 1) { //行標題頭
Item.nFormat = DT_CENTER|DT_VCENTER
|DT_SINGLELINE|DT_END_ELLIPSIS
|DT_NOPREFIX;
Item.strText.Format(_T("%d"),row);
}
else if(col==1){ //第一列的值
Item.nFormat = DT_CENTER|DT_VCENTER
|DT_SINGLELINE|DT_END_ELLIPSIS
|DT_NOPREFIX;
str="aa";
Item.strText.Format(_T("%s"),str);
}else if(col==2){ //第二列第值
Item.nFormat = DT_CENTER|DT_VCENTER
|DT_SINGLELINE|DT_END_ELLIPSIS
|DT_NOPREFIX;
CString str;
str="bb";
Item.strText.Format(_T("%s"),str);
}
m_pGridCtrl->SetItem(&Item);
}
m_pGridCtrl->AutoSize();

//--------------設置行列距------------------
for(int a=1;a<m;a++)
m_pGridCtrl->SetRowHeight(a,21); //設置各行高
m_pGridCtrl->SetRowHeight(0,24); //設置0行高
m_pGridCtrl->SetColumnWidth(1,110); //設置2列寬
m_pGridCtrl->SetColumnWidth(2,160); //設置3列寬
m_pGridCtrl->SetColumnWidth(3,100); //設置4列寬
}
上例取自實際工程,稍有修改!
部分注釋:
void SetVirtualMode(TRUE) //設為虛模式
BOOL SetRowCount(int nRows) //設置總的行數。
BOOL SetFixedRowCount(int nFixedRows = 1)//設置固定的行數據
BOOL SetColumnCount(int nCols) //設置列數
BOOL SetFixedColumnCount(int nFixedCols = 1)//設置固定的列數


步驟五: 添加WM_SIZE消息,調整控件的界面占屏幕大小

??if(m_pGridCtrl->GetSafeHWnd())
???{
??????CRect rect;
?????GetClientRect(rect);
?????m_pGridCtrl->MoveWindow(rect);
???}



?在對話框中的使用方法

步驟一 創建數據顯示表格對話框

在資源管理器中新創建一個對話框,假設為CDlgTestReportBox。 從工具箱中加入Custom Control,就是人頭像的那個,將其區域拉伸至要顯示數據表格的大小,充滿整個對話框。

在CDlgTestReportBox類的頭文件中:

#include "GridCtrl.h"

再定義成員變量:

CGridCtrl* m_pGrid;

添加OnShowWindow()消息處理函數如下:

void CDlgTestReportBox::OnShowWindow(BOOL bShow, UINT nStatus) 
{
CDialog::OnShowWindow(bShow, nStatus);
// TODO: Add your message handler code here
if(m_pGrid!=NULL)
{
delete m_pGrid;
m_pGrid=NULL;
}
if(m_pGrid==NULL)
{
m_pGrid=new CGridCtrl;
CRect rect;
GetDlgItem(IDC_ReportAera)->GetWindowRect(rect); //得到顯示區域
ScreenToClient(&rect);
m_pGrid->Create(rect,this,100);
m_pGrid->SetEditable(false);
m_pGrid->SetTextBkColor(RGB(0xFF, 0xFF, 0xE0)); //黃色背景
try
{
m_pGrid->SetRowCount(10); //初始為10行
m_pGrid->SetColumnCount(11); //初始化為11列
m_pGrid->SetFixedRowCount(1); //表頭為一行
m_pGrid->SetFixedColumnCount(1); //表頭為一列
}
catch (CMemoryException* e)
{
e->ReportError();
e->Delete();
// return FALSE;
}
for (int row = 0; row < m_pGrid->GetRowCount(); row++)
for (int col = 0; col < m_pGrid->GetColumnCount(); col++)
{
//設置表格顯示屬性
GV_ITEM Item;
Item.mask = GVIF_TEXT|GVIF_FORMAT;
Item.row = row;
Item.col = col;
if(row==0&&col==0) //第(0,0)格
{
Item.nFormat = DT_CENTER|DT_WORDBREAK;
Item.szText.Format(_T("報表顯示"),col);
}
else if (row < 1) //設置0行表頭顯示
{
Item.nFormat = DT_CENTER|DT_WORDBREAK;
Item.szText.Format(_T(" 項目%d"),col);
}
else if (col < 1) //設置0列表頭顯示
{
if(row< m_pGrid->GetRowCount()-4)
{
Item.nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS;
Item.szText.Format(_T("第%d次"),row);
}
}
else
{
Item.nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS;
Item.szText.Format(_T(""),2);
}
m_pGrid->SetItem(&Item);
}
m_pGrid->Invalidate();
}
//--------------設置行列距------------------
for(int a=0;aGetRowCount();a++)
m_pGrid->SetRowHeight(a,16); //設置各行高
m_pGrid->SetColumnWidth(0,58); //設置0列寬
for(int b=1;bGetColumnCount();b++)
m_pGrid->SetColumnWidth(b,59); //設置各列寬
}

?

步驟二 嵌入上面的對話框 顯示數據

在你需要顯示數據的對話框上的頭文件中,假設為CDlgTest,加入

#include "GridCtrl.h"

CDlgTestReportBox* m_pTestReportBox;

將數據顯示對話框放入你的對話框相應位置上,在CDlgTest::OnInitDialog() 中:

if(!m_pTestReportBox)
{
?????m_pTestReportBox=new CDlgTestReportBox(this);
}

m_pTestReportBox->Create(IDD_DlgTestReportBox,this);

//定義區域變量
CRect rectDraw;
GetDlgItem(IDC_AeraReport)->GetWindowRect(rectDraw);
ScreenToClient(&rectDraw); //動態測試數據顯示區域rectDraw

//將對應的對話框放到指定區域
m_pTestReportBox->MoveWindow(rectDraw);
m_pTestReportBox->ShowWindow(SW_SHOW);

自定義填充數據的函數:CDlgTest::FillGrid() 如下:

CGridCtrl* pGrid=m_pTestReportBox->m_pGrid;
for (int row = pGrid->GetRowCount()-1; row >= pGrid->GetRowCount()-3; row--)
{
for (int col = 1; col <= pGrid->GetColumnCount(); col++)
{
GV_ITEM Item;
Item.mask = GVIF_TEXT|GVIF_FORMAT;
Item.row = row;
Item.col = col;
if(row==pGrid->GetRowCount()-3&&col>0) //平均值
{
if(col==10){
Item.nFormat = DT_CENTER|DT_WORDBREAK;
Item.szText.Format(_T(" %6.2f "),avjch);
}
else{
Item.nFormat = DT_CENTER|DT_WORDBREAK;
Item.szText.Format(_T(" %6.2f "),av[col-1]);
}
}
pGrid->SetItem(&Item); //提交數據
if(row==0||col==0)
{
COLORREF clr = RGB(0, 0, 0);
pGrid->SetItemBkColour(row, col, clr);
pGrid->SetItemFgColour(row, col, RGB(255,0,0));
}
}//循環結束
pGrid->Invalidate();
}
好累啊,忙了一天時間終于寫完了!


posted @ 2006-06-23 23:16 讓心飛翔 閱讀(10217) | 評論 (12)編輯 收藏

一、ADO概述
ADO是Microsoft為最新和最強大的數據訪問范例 OLE DB 而設計的,是一個便于使用的應用程序層接口。ADO 使您能夠編寫應用程序以通過 OLE. DB 提供者訪問和操作數據庫服務器中的數據。ADO 最主要的優點是易于使用、速度快、內存支出少和磁盤遺跡小。ADO 在關鍵的應用方案中使用最少的網絡流量,并且在前端和數據源之間使用最少的層數,所有這些都是為了提供輕量、高性能的接口。之所以稱為 ADO,是用了一個比較熟悉的暗喻,OLE 自動化接口。
OLE DB是一組”組件對象模型”(COM) 接口,是新的數據庫低層接口,它封裝了ODBC的功能,并以統一的方式訪問存儲在不同信息源中的數據。OLE DB是Microsoft UDA(Universal Data Access)策略的技術基礎。OLE DB 為任何數據源提供了高性能的訪問,這些數據源包括關系和非關系數據庫、電子郵件和文件系統、文本和圖形、自定義業務對象等等。也就是說,OLE DB 并不局限于 ISAM、Jet 甚至關系數據源,它能夠處理任何類型的數據,而不考慮它們的格式和存儲方法。在實際應用中,這種多樣性意味著可以訪問駐留在 Excel 電子數據表、文本文件、電子郵件/目錄服務甚至郵件服務器,諸如 Microsoft Exchange 中的數據。但是,OLE DB 應用程序編程接口的目的是為各種應用程序提供最佳的功能,它并不符合簡單化的要求。您需要的API 應該是一座連接應用程序和OLE DB 的橋梁,這就是 ActiveX Data Objects (ADO)。
二、在VC中使用ADO(開發步驟好下:)
1、引入ADO庫文件
使用ADO前必須在工程的stdafx.h頭文件里用直接引入符號#import引入ADO庫文件,以使編譯器能正確編譯。代碼如下所示:
用#import引入ADO庫文件
?
#import "c:\program files\common files\system\ado\msado15.dll"no_namespaces rename("EOF" adoEOF")
?
這行語句聲明在工程中使用ADO,但不使用ADO的名字空間,并且為了避免常數沖突,將常數EOF改名為adoEOF。現在不需添加另外的頭文件,就可以使用ADO接口了。
2、初始化OLE/COM庫環境
必須注意的是,ADO庫是一組COM動態庫,這意味應用程序在調用ADO前,必須初始化OLE/COM庫環境。在MFC應用程序里,一個比較好的方法是在應用程序主類的InitInstance成員函數里初始化OLE/COM庫環境。
?
BOOL CMyAdoTestApp::InitInstance()
{
if(!AfxOleInit())//這就是初始化COM庫
{
AfxMessageBox(“OLE初始化出錯!”);
return FALSE;
}
……
}
?
3、ADO接口簡介
ADO庫包含三個基本接口:_ConnectionPtr接口、_CommandPtr接口和_RecordsetPtr接口。
_ConnectionPtr 接口返回一個記錄集或一個空指針。通常使用它來創建一個數據連接或執行一條不返回任何結果的SQL語句,如一個存儲過程。使用 _ConnectionPtr接口返回一個記錄集不是一個好的使用方法。對于要返回記錄的操作通常用_RecordserPtr來實現。而用 _ConnectionPtr操作時要想得到記錄條數得遍歷所有記錄,而用_RecordserPtr時不需要。
_CommandPtr 接口返回一個記錄集。它提供了一種簡單的方法來執行返回記錄集的存儲過程和SQL語句。在使用_CommandPtr接口時,你可以利用全局 _ConnectionPtr接口,也可以在_CommandPtr接口里直接使用連接串。如果你只執行一次或幾次數據訪問操作,后者是比較好的選擇。但 如果你要頻繁訪問數據庫,并要返回很多記錄集,那么,你應該使用全局_ConnectionPtr接口創建一個數據連接,然后使用_CommandPtr 接口執行存儲過程和SQL語句。
_RecordsetPtr是一個記錄集對象。與以上兩種對象相比,它對記錄集提供了更多的控制功能,如記錄鎖定,游標控制等。同 _CommandPtr接口一樣,它不一定要使用一個已經創建的數據連接,可以用一個連接串代替連接指針賦給 _RecordsetPtr的connection成員變量,讓它自己創建數據連接。如果你要使用多個記錄集,最好的方法是同Command對象一樣使用 已經創建了數據連接的全局_ConnectionPtr接口
,然后使用_RecordsetPtr執行存儲過程和SQL語句。 
4、使用_ConnectionPtr接口
_ConnectionPtr主要是一個連接接口,取得與數據庫的連接。它的連接字符串可以是自己直接寫,也可以指向一個ODBC DSN。
?
_ConnectionPtr pConn;
if (FAILED(pConn.CreateInstance("ADODB.Connection")))
{
AfxMessageBox("Create Instance failed!");
return;
}

CString strSRC;
strSRC="Driver=SQL Server;Server=";
strSRC+="suppersoft";
strSRC+=";Database=";
strSRC+="mydb";
strSRC+=";UID=SA;PWD=";
CString strSQL = "Insert into student(no,name,sex,address) values(3,'aaa','male','beijing')";
_variant_t varSRC(strSRC);
_variant_t varSQL(strSQL);
_bstr_t bstrSRC(strSRC);
if (FAILED(pConn->Open(bstrSRC,"","",-1)))
{
AfxMessageBox("Can not open Database!");
pConn.Release();
return;
}
COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
pConn->Execute(_bstr_t(strSQL),&vtOptional,-1);
pConn.Release();
AfxMessageBox("ok!");
?
5、使用_RecordsetPtr接口(以連接SQL Server為例)

_RecordsetPtr pPtr;
if (FAILED(pPtr.CreateInstance("ADODB.Recordset")))
{
AfxMessageBox("Create Instance failed!");
return FALSE;
}
CString strSRC;
strSRC="Driver=SQL Server;Server=";
strSRC+="210.46.141.145";
strSRC+=";Database=";
strSRC+="mydb";
strSRC+=";UID=sa;PWD=";
strSRC+="sa";
CString strSQL = "select id,name,gender,address from personal";
_variant_t varSRC(strSRC);
_variant_t varSQL(strSQL);
if(FAILED(pPtr->Open(varSQL,varSRC,adOpenStatic,adLockOptimistic,adCmdText)))
{
AfxMessageBox("Open table failed!");
pPtr.Release();
return FALSE;
}
while(!pPtr->GetadoEOF())
{
_variant_t varNo;
_variant_t varName;
_variant_t varSex;
_variant_t varAddress;
varNo = pPtr->GetCollect ("id");
varName = pPtr->GetCollect ("name");
varSex = pPtr->GetCollect ("gender");
varAddress = pPtr->GetCollect ("address");
CString strNo =(char *)_bstr_t(varNo);
CString strName =(char *)_bstr_t(varName);
CString strSex =(char *)_bstr_t(varSex);
CString strAddress =(char *)_bstr_t(varAddress);
strNo.TrimRight();
strName.TrimRight();
strSex.TrimRight();
strAddress.TrimRight();
int nCount = m_list.GetItemCount();
int nItem = m_list.InsertItem (nCount,_T(""));
m_list.SetItemText (nItem,0,strNo);
m_list.SetItemText (nItem,1,strName);
m_list.SetItemText (nItem,2,strSex);
m_list.SetItemText (nItem,3,strAddress);
pPtr->MoveNext();
}
pPtr->Close();
pPtr.Release();
?
6、使用_CommandPtr接口
_CommandPtr接口返回一個Recordset對象,并且提供了更多的記錄集控制功能,以下代碼示例了使用_CommandPtr接口的方法:
代碼11:使用_CommandPtr接口獲取數據
?
_CommandPtr pCommand;
_RecordsetPtr pRs;
pCommand.CreateInstance(__uuidof(Command));
pCommand->ActiveConnection=pConn;
pCommand->CommandText="select * from student";
pCommand->CommandType=adCmdText;
pCommand->Parameters->Refresh();
pRs=pCommand->Execute(NULL,NULL,adCmdUnknown);
_variant_t varValue = pRs->GetCollect("name");
Cstring strValue=(char*)_bstr_t(varValue);
?
7、關于數據類型轉換由于COM對象是跨平臺的,它使用了一種通用的方法來處理各種類型的數據,
因此Cstring 類和COM對象是不兼容的,我們需要一組API來轉換COM對象和C++類型的數據。_vatiant_t和_bstr_t就是這樣兩種對象。它們提供了通用的方法轉換COM對象和C++類型的數據。
posted @ 2006-06-23 23:14 讓心飛翔 閱讀(1985) | 評論 (0)編輯 收藏

??? Forms2.0系列的控件,如: Microsoft forms 2.0 labelMicrosoft forms 2.0 commandbutton等,其依賴的動態鏈接庫為Fm20.dlls。在使用過程中我發現,如果在發布軟件的時候,用戶的客戶機上沒有安裝word的話,程序就不能運行(雖然程序運行了,但是看不到界面出現)。 后來在網上搜索了很多資料,終于找到了問題的關鍵,在微軟網站上找到關于這個問題的解釋為: Fm20.dlls 不是可以重分配的,你必須安裝一個象OFFICE97那樣的系統在你的目標客戶機上作為你軟件分發的一部分。 如果不安裝Microsoft Office 97那樣的系統的話,即使你使用regsvr32注冊都沒有作用(我翻譯的,有點不通順哦^_^)。
??? 最終的解決辦法就是,做為Microsoft Office 97的替代,你可以免費下載和安裝Microsoft ActiveX Control Pad. 安裝完畢,客戶機上就可以無需安裝office而使用你的程序了。[需要的請留下email,我會發給你的]
posted @ 2006-06-23 23:11 讓心飛翔 閱讀(1313) | 評論 (0)編輯 收藏

下面是我在編程中運用CTypedPtrMap指針模板類的方法,其存儲結構占用物理空間小,比單純的用數組結構存儲的文件將小很多,所以是一種非常推薦的存儲及讀取文件的方法。

你必須在stdafx.h文件中 包含? #include <afxtempl.h>??? // MFC templates
在頭文件中包含? #include <io.h>

其中 CBank.h文件如下:

class CBank : public CObject? 
{
DECLARE_SERIAL(CBank)?? //聲明序列化存儲
public:
??? ?? CBank();
?????? CBank(CString str){ m_bankname = str; }
?????? CBank(const CBank &b){ m_bankname= b.m_bankname;} //拷貝構造函數
????? ? virtual ~CBank();
private:
?????? CString? m_bankname;
public:
??? virtual void Serialize(CArchive& ar);
};

typedef CTypedPtrMap<CMapStringToOb,

???????????????????? CString,

???????????????????? CBank*>CBanktmp;? //這個才是我們根據此類生成的類型

它的實現文件.cpp如下:

IMPLEMENT_SERIAL(CBank, CObject, 1)?? //實現序列化存儲
CBank::CBank()
{
? ? m_bankname="";
}
CBank::~CBank()
{

}
void CBank::Serialize(CArchive& ar)
{
??? if (ar.IsLoading())
??? {
??????? ar >> m_bankname;
??? }
??? else
??? {
??????? ar << m_bankname;
??? }
}

/*----------------------------------------------------
從文件中讀取參數:
注意: 其中的m_map是這樣定義的:CBanktmp? m_map;
-------------------------------------------------*/

void CDlgBankIn::LoadBankName()
{
?????? UINT? nFlags = CFile::typeBinary |CFile::modeReadWrite;
?????? if(_access(_T("BankName.dat"),0))
?????? {
????????????? nFlags |= CFile::modeCreate;
?????? }
?????? CFile file;
?????? CFileException fe;
?????? if (file.Open(_T("BankName.dat"),nFlags, &fe))
?????? {
?????????? if(file.GetLength()==0)?? //如果文件為空則不進行讀取操作
???? ????? {
?????????? }
?????????? else
?????????? {
??????????????? CArchive ar(&file, CArchive::load);
??????????????? m_map.Serialize(ar);?? //讀取文件
?????????????? //根據文件內容填充列表框
???? ?????????? POSITION?? pos;
??????????????? CString??? strKey;
??????????????? CBank?? *pB=NULL;
??????????????? for( pos = m_map.GetStartPosition(); pos != NULL; )
??????????????? {
??????????????????? m_map.GetNextAssoc(pos,strKey,(CBank*)pB);
??????????????????? m_CmbBank.AddString(strKey);
??????????????? }
??????????????? delete? pB;
????????????? }
?????? }
?????? file.Close();
}

/*-------------------------------------------------
功能: 先打開文件,然后查找文件中是否有與編輯框關鍵字相同的內容,
??? ?? 如果有相同內容則不添加,如果沒有相同內容則寫文件.
------------------------------------- ------------*/

void CDlgBankList::OnBtnAdd() 
{
?????? // TODO: Add your control notification handler code here
?????? CString? strKey;
?????? GetDlgItemText(IDC_EDITBank,strKey);
?????? if (0 != strKey.GetLength())
?????? {
????????? CBank? *pB;
????????? //打開文件
????? ?? UINT? nFlags = CFile::typeBinary |CFile::modeRead;
????????? CFile file;
????????? CFileException fe;
????????? if (file.Open(_T("BankName.dat"),nFlags, &fe))
????????? {
???????????????? if(file.GetLength()==0)? //如果文件為空則不進行序列化操作
???? ??????????? {

???????????????? }
???????????????? else
???????????????? {
????????????????? CArchive ar(&file, CArchive::load);
????????????????? m_map.Serialize(ar);
???????????????? }
?????????????? //分析文件并給文件添加編輯框的內容
???? ?????????? if(!m_map.Lookup(strKey,(CBank*)pB))? //當不存在時才需要添加
????? ??????????? {
????????????????????? if (CB_ERR != m_ListBox.AddString(strKey))
????????????????????? {
???????????????????????? m_map.SetAt(strKey, new CBank(strKey));? //給關鍵字strKey賦值
???? ???????????????? }
???????????????? }
????????? }
?????? file.Close();

?????? //存儲文件
???? nFlags = CFile::typeBinary |CFile::modeWrite;
?????? if (file.Open(_T("BankName.dat"),nFlags, &fe))
?????? {
??????????? CArchive ar(&file, CArchive::store);
??????????? m_map.Serialize(ar);?? //序列化存儲
???? }
??? }
}

/*-------------------------------------------------
功能: 先打開文件,然后查找文件中的關鍵字,
????找到后則刪除此關鍵字, 但是注意關鍵字對應的內容仍然沒有刪除,這點期待改進.
-------------------------------------------------*/

void CDlgBankList::OnBtnDel() 
{
?????? // TODO: Add your control notification handler code here
?????? int iIndex;??????
?????? CString? strKey;
?????? if(LB_ERR!=m_ListBox.GetCurSel())
?????? {
??????? //打開文件
?????& nbsp;???? UINT? nFlags = CFile::typeBinary |CFile::modeRead;
?????????? CFile file;
?????????? CFileException fe;
?????????? if (file.Open(_T("BankName.dat"),nFlags, &fe))
?????????? {
????????????? CArchive ar(&file, CArchive::load);
????????????? m_map.Serialize(ar);?
????????????? iIndex=m_ListBox.GetCurSel();
????????????? m_ListBox.GetText(iIndex,strKey);
????????????? m_ListBox.DeleteString(iIndex);
????????????? //分析文件并給文件添加編輯框的內容
???? ????????? CBank? *pB=NULL;
????????????? if(m_map.Lookup(strKey,(CBank*)pB))
????????????? {
????????????????? m_map.RemoveKey(strKey);?? //刪除關鍵字,但沒有刪除關鍵字對應的內容
???? ????????? }
??????????? }
??????????? file.Close();
??????????? //存儲文件
????? ???? nFlags = CFile::typeBinary |CFile::modeWrite;
?????????? if (file.Open(_T("BankName.dat"),nFlags, &fe))
?????????? {
??????????????? CArchive ar(&file, CArchive::store);
??????????????? m_map.Serialize(ar);?? //序列化存儲
????? ???? }
?????? }
}

posted @ 2006-06-23 23:07 讓心飛翔 閱讀(1952) | 評論 (0)編輯 收藏

僅列出標題  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久精品国产99精品国产亚洲性色 | 亚洲第一在线综合在线| 亚洲日本中文字幕区| 1000部国产精品成人观看| 欧美日韩一区在线观看| 欧美日韩不卡视频| 欧美视频第二页| 国产伦精品一区二区三区| 国产一区二区三区四区| 在线观看91精品国产麻豆| 亚洲国产婷婷| 亚洲小说欧美另类婷婷| 欧美自拍偷拍| 欧美成人综合一区| 一区二区高清视频| 久久精品国产免费观看| 欧美高清在线精品一区| 国产精品久久久久7777婷婷| 国产一区二区电影在线观看| 亚洲高清不卡在线观看| 亚洲小说区图片区| 久久这里有精品15一区二区三区| 亚洲成人在线视频播放 | 久久久精品999| 蜜臀91精品一区二区三区| 欧美电影在线观看完整版| 国产精品福利久久久| 国内偷自视频区视频综合| 日韩一级大片| 久久久无码精品亚洲日韩按摩| 亚洲国产精品专区久久| 日韩亚洲一区二区| 久热这里只精品99re8久| 欧美视频在线视频| 在线成人av.com| 午夜精品久久久久久久99樱桃| 欧美大片一区| 欧美一区二区三区免费视| 欧美日韩国产首页在线观看| 激情懂色av一区av二区av| 99精品国产在热久久婷婷| 久久久久久精| 在线视频一区观看| 欧美精品aa| 91久久综合亚洲鲁鲁五月天| 久久国产高清| 亚洲午夜在线| 国产精品ⅴa在线观看h| 亚洲精品在线电影| 欧美成人免费全部| 欧美在线观看www| 国产精品日本精品| 一区二区三区你懂的| 亚洲第一主播视频| 老司机亚洲精品| 午夜视频一区在线观看| 91久久夜色精品国产九色| 欧美一级免费视频| 国产精品资源在线观看| 亚洲天堂成人在线视频| 亚洲激情专区| 欧美jjzz| 亚洲日本成人网| 亚洲福利在线观看| 欧美福利在线观看| 日韩午夜在线| 亚洲看片一区| 另类图片国产| 久久国产主播精品| 韩国在线视频一区| 久久久国产精彩视频美女艺术照福利 | 欧美国产日本在线| 另类成人小视频在线| 在线电影欧美日韩一区二区私密| 久久精品盗摄| 久久aⅴ国产欧美74aaa| 在线成人激情黄色| 亚洲精品国产精品国自产观看| 欧美剧在线免费观看网站| 亚洲午夜激情网页| 午夜在线一区| 亚洲黄色av| 一区二区三欧美| 国产日韩欧美高清免费| 蜜月aⅴ免费一区二区三区| 欧美成人精品一区二区| 中文在线一区| 欧美在线黄色| 一区二区三区视频在线看| 亚洲调教视频在线观看| 国产综合香蕉五月婷在线| 亚洲高清一区二| 国产精品理论片在线观看| 米奇777超碰欧美日韩亚洲| 欧美日韩高清在线| 久久久久久久久久久久久9999| 嫩草伊人久久精品少妇av杨幂| 亚洲一级一区| 久久天天躁狠狠躁夜夜av| 亚洲视频在线观看三级| 欧美一级在线亚洲天堂| 久久成人18免费网站| 亚洲精品麻豆| 欧美在线国产| 亚洲视频欧美在线| 久久久成人精品| 亚洲欧美日韩一区| 欧美激情视频一区二区三区在线播放 | 国产精品户外野外| 美女在线一区二区| 国产日韩欧美精品| 亚洲人成7777| 国产亚洲人成网站在线观看| 欧美成人一区二区在线| 国产精品网站在线观看| 亚洲激情一区| 在线免费精品视频| 亚洲综合日本| 在线视频精品一| 久久在线视频| 久久精品视频一| 国产精品白丝jk黑袜喷水| 免费久久99精品国产自| 国产一区二区三区奇米久涩| 亚洲手机视频| 亚洲一区黄色| 欧美日韩国产综合一区二区| 亚洲高清不卡| 亚洲精品日韩欧美| 免费观看成人鲁鲁鲁鲁鲁视频| 久久久国产视频91| 国产精品自拍三区| 亚洲女人小视频在线观看| 亚洲欧美国产不卡| 欧美亚洲不卡| 中文在线资源观看网站视频免费不卡 | 午夜欧美不卡精品aaaaa| 欧美激情免费在线| 欧美国产精品人人做人人爱| 在线播放日韩专区| 毛片av中文字幕一区二区| 老牛影视一区二区三区| 国产日韩专区| 久久av资源网| 欧美成人精品不卡视频在线观看| 伊人久久久大香线蕉综合直播| 欧美专区福利在线| 美腿丝袜亚洲色图| 亚洲精品你懂的| 欧美激情一区二区三区蜜桃视频 | 国内精品久久久久影院 日本资源 国内精品久久久久伊人av | 亚洲婷婷综合色高清在线| 亚洲影音先锋| 国产精品综合| 久久精品视频免费观看| 免费看成人av| av成人天堂| 国产日韩欧美视频| 久久亚洲综合| 99精品国产高清一区二区| 欧美一区午夜精品| 亚洲国产精品精华液网站| 欧美日韩亚洲在线| 欧美一区2区三区4区公司二百 | 亚洲自拍三区| 99国产一区二区三精品乱码| 欧美成人r级一区二区三区| 亚洲精品久久久久久久久| 亚洲欧美激情精品一区二区| 国产精品一区二区视频| 久久久久久久久久久久久久一区 | 欧美亚洲系列| 欧美激情视频网站| 亚洲欧美激情一区二区| 一区精品在线| 国产精品成人观看视频国产奇米| 香蕉成人伊视频在线观看| 欧美激情按摩在线| 亚洲欧美国产精品专区久久| 好吊色欧美一区二区三区视频| 欧美另类亚洲| 久久动漫亚洲| 亚洲色在线视频| 亚洲高清成人| 久久免费视频一区| 亚洲欧美在线高清| 亚洲精品中文字幕有码专区| 国产免费观看久久黄| 欧美日韩国产成人| 狂野欧美激情性xxxx欧美| 亚洲欧美日韩在线一区| 日韩视频在线观看国产| 欧美大片一区| 噜噜噜噜噜久久久久久91| 午夜视频在线观看一区| 在线亚洲成人| 日韩视频免费看| 最近中文字幕日韩精品| 含羞草久久爱69一区| 国产精品视频xxxx|