- 考試環境: VS2010 (適用於NCEPU)
- 個人總結,禁止轉載
- 猜測考試題型爲:單文檔裏嵌入對話框
編譯異常處理方法
如果確認代碼無誤,選擇重新生成解決方案,嘗試能不能解決問題
1 基於對話框的應用程序
基礎知識
- 學會修改控件的ID
- 學會拖拽控件
- 學會修改Static Text\Button\對話框的標題(Caption)
- 學會給控件添加Value型變量[ctrl+shift+x]
- 學會設置Edit的只讀(readonly)
- 學會添加Button的click事件 [雙擊Button]
- 數據交換機制DDX/數據驗證機制DDV
- 修改對話框內控件的Tab順序[Ctrl+D]
- 關閉對話框
this->OnOK();
this->OnCancel();
或者修改ID爲IDOK, IDCANCEL
- 彈出對話框
前置操作:#include對話框的頭文件
CdialogPracticeDlg dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置處理何時用
// “確定”來關閉對話框的代碼
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置處理何時用
// “取消”來關閉對話框的代碼
}
注意:這段代碼必須要會,如果記不住:在XXXX(工程名).cpp裏面的InitInstance函數有類似的代碼,可以仿寫
- afxMessageBox
- 添加處理程序(以及錯誤添加的刪除)
- 新建對話框
然後雙擊或者右鍵添加類
#include "TipDlg.h"
void CdialogPracticeDlg::OnBnClickedButtonCalc()
{
CTipDlg dlg;
INT_PTR nResponse = dlg.DoModal();
if(nResponse == IDCANCEL)return;
UpdateData(TRUE);
m_dAns = m_dOp1 + m_dOp2;
UpdateData(FALSE);
}
- CString類的基本操作要會 文末拓展閱讀材料
CString變爲int:int y = _ttoi(year);
- 組合框(ComboBox)的基本使用和一些屬性
data 寫數據
droplist不能修改,只能選,dropdown可以改
一般把sort關掉
關聯變量:int 表示第幾個被選中(從0開始,記得設置sort爲false,-1表示默認不選中)
m_nChoose是關聯的int變量,sort設置爲false,數據是+;-;*;/;
void CdialogPracticeDlg::OnBnClickedButtonCalc()
{
UpdateData(TRUE);
if(m_nChoose == -1){
AfxMessageBox(_T("please choosee an operator"));
return;
}
switch(m_nChoose){
case 0:
m_dAns = m_dOp1 + m_dOp2;
break;
case 1:
m_dAns = m_dOp1 - m_dOp2;
break;
case 2:
m_dAns = m_dOp1 * m_dOp2;
break;
case 3:
if( fabs(m_dOp2) < 1e-10 ){
AfxMessageBox(_T("Error"));
return;
}
m_dAns = m_dOp1 / m_dOp2;
break;
}
UpdateData(FALSE);
}
給combo box關聯 control類型變量m_comboCalc
定位到:CXXXXXXXDlg::OnInitDialog(),在TODO後面添加代碼
m_comboCalc.AddString(_T(“+"));動態添加選項
動態添加:
for(int i=2000;i<=2020;i++){
CString str;
str.Format(_T("%d"),i);
this->m_combo_year.AddString(str);
}
獲得當前選中的選項和文本
CString year;
int nChoose = this->m_combo_year.GetCurSel();
this->m_combo_year.GetLBText(nChoose,year);
修改選項:SetCurSel()
清空選項: ResetContent()
選項變化事件:CBN_SELCHANGE
如果是dropdown,怎麼獲得輸入框裏的文本?m_combo.GetWindowTextW()
拓展閱讀: https://blog.csdn.net/qq_33583069/article/details/106167719
- 根據ID獲得控件變量的方法:
CButton *p8 = ((CButton*)GetDlgItem(IDC_B8));
- Radio Button 單選互斥的操作
根據tab順序,直到新的group:true,否則後面的都互斥
GetCheck()
判斷是否選中,0未選中1選中 - 設置Button不可用/可用
pButton->EnableWindow(FALSE);
pButton->EnableWindow(TRUE);
綜合案例:計算器
https://blog.csdn.net/qq_33583069/article/details/106183203
// CCalculatorDlg 消息處理程序
BOOL CCalculatorDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 將“關於...”菜單項添加到系統菜單中。
// IDM_ABOUTBOX 必須在系統命令範圍內。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 設置此對話框的圖標。當應用程序主窗口不是對話框時,框架將自動
// 執行此操作
SetIcon(m_hIcon, TRUE); // 設置大圖標
SetIcon(m_hIcon, FALSE); // 設置小圖標
// TODO: 在此添加額外的初始化代碼
CButton* pRadioDec = (CButton*)GetDlgItem(IDC_RADIO_DEC);
pRadioDec->SetCheck(TRUE);
CButton *pCheck = (CButton*)GetDlgItem(IDC_CHECK);
pCheck->SetCheck(TRUE);
return TRUE; // 除非將焦點設置到控件,否則返回 TRUE
}
void CCalculatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向對話框添加最小化按鈕,則需要下面的代碼
// 來繪製該圖標。對於使用文檔/視圖模型的 MFC 應用程序,
// 這將由框架自動完成。
void CCalculatorDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用於繪製的設備上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使圖標在工作區矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 繪製圖標
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//當用戶拖動最小化窗口時系統調用此函數取得光標
//顯示。
HCURSOR CCalculatorDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CCalculatorDlg::OnBnClickedB0(){
m_nValue = m_nValue*10;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedB1()
{
m_nValue = m_nValue*10+1;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedB2()
{
m_nValue = m_nValue*10+2;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedB3()
{
m_nValue = m_nValue*10+3;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedB4()
{
m_nValue = m_nValue*10+4;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedB5()
{
m_nValue = m_nValue*10+5;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedB6()
{
m_nValue = m_nValue*10+6;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedB7()
{
m_nValue = m_nValue*10+7;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedB8()
{
m_nValue = m_nValue*10+8;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedB9()
{
m_nValue = m_nValue*10+9;
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedBtnAdd()
{
UpdateData(TRUE);
m_nOp1 = m_nValue;
m_nValue = 0;
op = '+';
}
void CCalculatorDlg::OnBnClickedBtnSub()
{
UpdateData(TRUE);
m_nOp1 = m_nValue;
m_nValue = 0;
op = '-';
}
void CCalculatorDlg::OnBnClickedBtnMul()
{
UpdateData(TRUE);
m_nOp1 = m_nValue;
m_nValue = 0;
op = '*';
}
void CCalculatorDlg::OnBnClickedBtnDiv()
{
UpdateData(TRUE);
m_nOp1 = m_nValue;
m_nValue = 0;
op = '/';
}
void CCalculatorDlg::OnBnClickedBtnClr()
{
m_nValue = 0;
op = 0;
m_nOp1 = 0;
m_nOp2 = 0;
UpdateData(FALSE);
}
int octToDec(int x){
int result = 0;
int w = 1;
while(x){
if(x&1)result += w*(x%8);
w *= 8;
x /= 8;
}
return result;
}
void CCalculatorDlg::OnBnClickedBtnEqu()
{
if(op == 0){
AfxMessageBox(_T("No Operand"));
return;
}
m_nOp2 = m_nValue;
CButton *pRadioOct = ((CButton*)GetDlgItem(IDC_RADIO_OCT));
if(pRadioOct->GetCheck()==1){
m_nOp1 = octToDec(m_nOp1);
m_nOp2 = octToDec(m_nOp2);
}
switch(op){
case '+':
m_nValue = m_nOp1 + m_nOp2;
break;
case '-':
m_nValue = m_nOp1 - m_nOp2;
break;
case '*':
m_nValue = m_nOp1 * m_nOp2;
break;
case '/':
if(m_nOp2 == 0){
AfxMessageBox(_T("Error"));
return;
}
m_nValue = m_nOp1 / m_nOp2;
break;
}
if(pRadioOct->GetCheck()==1){
char s8[30];
itoa(m_nValue,s8,8);
m_nValue = atoi(s8);
}
UpdateData(FALSE);
m_nValue = 0;
op = 0;
m_nOp1 = 0;
m_nOp2 = 0;
}
void CCalculatorDlg::OnBnClickedRadioDec()
{
CButton *p8 = ((CButton*)GetDlgItem(IDC_B8));
CButton *p9 = ((CButton*)GetDlgItem(IDC_B9));
p8->EnableWindow(TRUE);
p9->EnableWindow(TRUE);
transform();
}
void CCalculatorDlg::transform(){
UpdateData(TRUE);
CButton *pRadioOct = ((CButton*)GetDlgItem(IDC_RADIO_OCT));
if(pRadioOct->GetCheck() == 0) {
m_nValue = octToDec(m_nValue);
}
else {
char s8[30];
itoa(m_nValue,s8,8);
m_nValue = atoi(s8);
}
UpdateData(FALSE);
}
void CCalculatorDlg::OnBnClickedRadioOct()
{
CButton *p8 = ((CButton*)GetDlgItem(IDC_B8));
CButton *p9 = ((CButton*)GetDlgItem(IDC_B9));
p8->EnableWindow(FALSE);
p9->EnableWindow(FALSE);
transform();
}
void CCalculatorDlg::OnBnClickedCheck()
{
CButton *pRadioDec = (CButton*)GetDlgItem(IDC_RADIO_DEC);
CButton *pRadioOct = (CButton*)GetDlgItem(IDC_RADIO_OCT);
CButton *pCheck = (CButton*)GetDlgItem(IDC_CHECK);
if(pCheck->GetCheck()==0){
pRadioDec->EnableWindow(FALSE);
pRadioOct->EnableWindow(FALSE);
} else {
pRadioDec->EnableWindow(TRUE);
pRadioOct->EnableWindow(TRUE);
}
}
綜合案例2 登錄對話框
考察點:重寫CEdit
https://blog.csdn.net/qq_33583069/article/details/106194453
如果只是限定Edit輸入數字的話
改成True就好
如果是限定用字母的話,需要自己重寫,這裏纔是本節重點(考點)
重點
基類選擇爲:CEdit
添加WM_CHAR消息
-
旋鈕應該不考
-
圖標 bitmap
HBITMAP hBmp=::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1));
m_Btn.SetBitmap(hBmp);
2 單文檔應用程序
- 修改XXXView.cpp的OnDraw方法
void CSDIView::OnDraw(CDC* pDC)
{
CSDIDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此處爲本機數據添加繪製代碼
pDC->TextOut(50,50,_T("hello,單文檔"));
}
-
pDC->TextOut(50,50,_T("hello,單文檔"));
-
CreatePointFont()
void CApp15View::OnDraw(CDC* pDC) { CApp15Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; CFont newFont; // 新字體 CFont *pOldFont; // 選擇新字體之前的字體 newFont.CreatePointFont(180, _T("隸書")); // 創建一種新的字體 pOldFont=(CFont*)pDC->SelectObject(&newFont); // 在指定位置輸出文本 pDC->TextOut(40,10,_T("你好!")); // 恢復以前的字體 pDC->SelectObject(pOldFont); pDC->TextOut(50,50, _T("這是我的第一個單文檔應用程序!")); }
-
pDC->SetTextColor(RGB(255,0,0));
、SetBkColor()
-
修改菜單,並添加處理事件
- 設置字體菜單
- CreateFontIndirect
- LogFont
- CFontDialog
void CSDIDoc::OnFontMenu() { CFontDialog dlg; if(dlg.DoModal() == IDOK){ LOGFONT lf; COLORREF color; dlg.GetCurrentFont(&lf); m_font.DeleteObject(); m_font.CreateFontIndirect(&lf); m_color = dlg.GetColor(); UpdateAllViews(NULL); } }
在view內裏刷新的話是
RedrawWindow()
- 添加字體菜單(自定義)
注意傳遞數據
void CSDIDoc::OnAddText() { CTextDlg dlg; if(dlg.DoModal() == IDOK){ m_nX = dlg.m_nX; m_nY = dlg.m_nY; m_strText = dlg.m_strText; } }
- 鼠標消息響應
- CPoint
void CSDIView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息處理程序代碼和/或調用默認值 m_posText = point; RedrawWindow(); CView::OnLButtonDown(nFlags, point); }
- 捕獲和釋放鼠標
-
修改ToolBar
ID和菜單欄上的某個菜單項保持一致 -
修改光標
- WM_SETCURSOR
BOOL CSDIView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { // TODO: 在此添加消息處理程序代碼和/或調用默認值 CSDIDoc* pDoc = GetDocument(); if(pDoc->m_nCursorFlag == 1){ ::SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR)); return TRUE; } else { ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); return TRUE; } }
-
修改標題
方法一:
方法二:資源->string table裏改mainframe
-
改圖標(Icon) 應用程序左上角的那個
改EXE圖標
-
對象鏈表
前置條件: 自定義數據類(例如文本信息類,繼承自CObject)
https://blog.csdn.net/qq_33583069/article/details/106239080
注意這裏記錄的是LOGFONT
void CSDIDoc::OnAppendText()
{
CFontDialog dlg;
LOGFONT lf;
COLORREF color;
if(dlg.DoModal() == IDOK){
dlg.GetCurrentFont(&lf);
color = dlg.GetColor();
CTextDlg tdlg;
if(tdlg.DoModal() == IDOK){
m_nX = tdlg.m_nX;
m_nY = tdlg.m_nY;
m_strText = tdlg.m_strText;
CMyText* pText = new CMyText(m_strText,CPoint(m_nX,m_nY),lf,color);
m_textList.AddTail(pText)
}
}
UpdateAllViews(NULL);
}
把view裏ondraw的後面的代碼刪完,重寫。
- POSITION
- GetHeadPosition
- GetNext
!!!這裏必考!!!
void CSDIView::OnDraw(CDC* pDC)
{
CSDIDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此處爲本機數據添加繪製代碼
POSITION pos = pDoc->m_textList.GetHeadPosition();
while(pos != NULL){
CMyText* pText = (CMyText*)pDoc->m_textList.GetNext(pos);
CFont font;
font.CreateFontIndirect(&pText->m_textFont);
CFont* pOld = pDC->SelectObject(&font);
pDC->SetTextColor(pText->m_textColor);
pDC->TextOut(pText->m_textPos.x,pText->m_textPos.y,pText->m_strText);
pDC->SelectObject(pOld);
}
}
刪除:
- RemoveAll
void CSDIDoc::RemoveTextList()
{
POSITION pos = m_textList.GetHeadPosition();
while(pos != NULL)
{
CMyText* pText = (CMyText*)m_textList.GetNext(pos);
delete pText;
}
m_textList.RemoveAll();
}
爲CMainFrame類添加窗口關閉響應函數OnClose()
- GetActiveDocument
void CMainFrame::OnClose()
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
CSDIDoc* pDoc = (CSDIDoc*)this->GetActiveDocument();
pDoc->RemoveTextList();
CFrameWndEx::OnClose();
}
- 新建/打開文件的處理
執行File|New命令時,將調用文檔類成員函數OnNewDocument(),該函數又要調用另一個成員函數DeleteContents()。另外執行File|Open命令時也會調用DeleteContents()函數。
注意:選虛函數!!!
void CSDIDoc::DeleteContents()
{
RemoveTextList();
CDocument::DeleteContents();
}
- 序列化
https://blog.csdn.net/qq_33583069/article/details/106239080
序列化這個不用記,在Doc裏有類似的代碼,直接複製然後修改就行
class CMyText:public CObject
{
DECLARE_SERIAL(CMyText)
public:
……
virtual void Serialize(CArchive &ar);
……
}
CArchive& operator<<(CArchive& ar, LOGFONT& logfont)
{
ar.Write(&logfont, sizeof(logfont));
return ar;
}
CArchive& operator>>(CArchive& ar, LOGFONT& logfont)
{
ar.Read(&logfont, sizeof(logfont));
return ar;
}
void CMyText::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << m_strText << m_textPos << m_textFont << m_textColor;
}
else
{
ar >> m_strText >> m_textPos >> m_textFont >> m_textColor;
}
}
void CSDIDoc::Serialize(CArchive& ar)
{
m_textList.Serialize(ar);
if (ar.IsStoring())
{
// TODO: 在此添加存儲代碼
}
else
{
// TODO: 在此添加加載代碼
}
}
設置文檔修改標記
綜合案例 畫圖系統
https://blog.csdn.net/qq_33583069/article/details/106248164