顯示具有 WIN32 API/MFC 標籤的文章。 顯示所有文章
顯示具有 WIN32 API/MFC 標籤的文章。 顯示所有文章

不知道怎麼跑出來的Executable for debug session Dialog

沒有留言:
調整專案檔,可以說是使用Visual Studio的一項最冒險的事了。
因為,幾乎沒有教學。

萬一,萬一了怎麼辦?
調爛了?
調出了一些問題了?

為了尋求最佳化而調整了專案檔,造成無法回頭(打的code都不能跑了?!)
除了使用「版本控制」來「穿越時空」之外.....

今天就遇到一個問題。
一個google不到的問題。
一個git無法回溯的問題。(該設定改變,不會改變.sln檔)

這問題,就取名為「不知道怎麼跑出來的Executable for debug session Dialog」

選debug模式。
在你complier 之後linking時,眼看著整個執行檔都編譯好了。
竟然跳一個鬼東西出來,要你選更詭異的東西?!

上網google就說「這是要debug .dll檔要用的」
問題是,我沒有要這麼做呀?!
而且沒有任何一篇教我怎麼取消的!唷!天哪~怎辦?要重建專案了嗎?

git也沒用!git reset --hard沒用!

怎辦?!

就在這快絕望的情況之下,我重開機了!
事實證明,沒用!

我開了另一個專案檔來跑跑看。
咦?它是OK的!(看來手動版本控制有其價值)

問題在於,它是怎麼OK麼的?
關鍵就在這!

  1. Local Windows Debugger
  2. Remote Widnows Debugger
這看似不起眼的小選項。正是元兇呀!
調整到Remote就會出問題,變成對dll檔debug,所以只要調回Local 就可以了。


此問題已重現過。
此原因會造成此問題,但是此問題不一定是此原因。

用MFC的手操作「真.Excel」

沒有留言:
這篇文章提及的程式碼,最早是由 自動產生Excel-流浪小築 學來的,這個網站除了這個,還有很多相關的技術可以學唷!很棒的前輩。

如果把Excel的OLE加到MFC的Project也請參考那篇文章就可以了(請務必完全照做一次)。
之後對於xlsFile的了解會更有幫助。

Excel的程式控制,似乎是辦公室應用裡算是高階的應用。用C++幾乎就是天一般的高度呀(哈哈)畢竟語法細節太多,整個類別全部使用的話,複雜度又太恐怖了。
雖然網路上有一個包好的XLSLIB可以使用,但是它....不適合我,我就自己做了一個。

這是以操作Excel的概念去設計的類別。每一個函數都盡可能的簡單好用。
只是最後插入圖表的部份因為我個人沒有在使用的關係,所以沒有做概念上的最佳化。
個人建議使用Design Pattern的組合模式來實現。

這個類別有公佈在PTT的CandCpp版、Google code、Github中。
在ptt獲得網友Edison.Shin的支援,讓它的功能更豐富。在此完全公開其程式碼提供大家使用。

PathFileExists()的用法

沒有留言:
BOOL PathFileExists(LPCTSTR pszPath);
檢查該目錄或檔案是否存在

要加.h檔

#include <shlwapi .h>


出現問題

error LNK2001: unresolved external symbol __imp__PathFileExistsA@4

解法:

除了使用設定專案[1]的方式解決,還可以在程式碼中加入這一行[2]
#pragma comment(lib,"Shlwapi.lib")

參考資料:
[1] PathFileExists用法--使用#include <shlwapi.h>
[2] 高手救命啊!!!Release时出现错误unresolved external!!!!!!

CString中找關鍵字的技巧

沒有留言:
我們常常要在字串截取一段之後,尋找想要的一邊、一段、一個字。
在此,將使用MFC的CString做示範。(因為這個我最常用!XD)


CString技法

abcdefghijklmnopqrstuvwxyz
字串搜尋

抱怨VC6//File: afx.ini Line: 122 的bug

沒有留言:
這個MFC的問題,我在網路上也是找了很久,沒有解,一直到無意間解開了!再重現。以下是以我自己的case做範例重現。


我的main project使用SDI,利用Menu打開各種的Dialog做操作,各個Dialog我都做一個sub project檔來個別開發、測試,最後在main project用#include的方式把code加入,再把dialog的interface給拉到main project,這樣就可以使用。

但是,這樣卻引發了一個隱藏的問題。

Circle::Animation();的做法

沒有留言:
在CPatternDlg中,宣告了一個圈圈物件
class CPatternDlg : public CDialog
{
    Circle m_Goal;
};
因為想要圈圈做動畫,並且用下面的呼叫方式(漂亮的語法)
void CPatternDlg::readyScreen()
{
//...
    m_Goal.Animation();
}
注意事項:
在此的動畫實作,是另外呼叫一個Thread來跑動畫程式段。

那一年滴掉的bug//物件的值莫名奇妙被改掉

沒有留言:

現象描述:

視窗程式介面

  1. 選取白色9點、按下「>>」(add)
  2. 在右邊的List,任意選取特定數字3個(可不連續),按下「<<」(delete)
  3. 最後List呈現的卻是從後面刪除選取數目


程式記錄檔:
藍色為最終結果,白色為被刪除掉的部份,黑框為被選取的項目
由程式記錄檔可以看見,資料的確被刪除,但是物件本身的資料卻變得和原本的不一樣

檔案處理API

沒有留言:
PathCombine function()  連接兩個字串、連接任何相對路徑 成為一個路徑。
PathFileExists()  確定檔案或資料夾的路徑是有效的。

BOOL CreateDirectory(LCPSTR, LPSECURITY_ATTRIBUTES);  //LPSECURITY_ATTRIBUTES = NULL  新增資料夾
BOOL RemoveDirectory(LCPSTR);  //移除資料夾
BOOL PathIsDirectory( LCPSTR );  //判斷資料夾是否存在

error C2440 誰是誰?

沒有留言:
error C2440: 'return' : cannot convert from 'class Cartridge' to 'class Cartridge *'

這麼看

error C2440: 'return' : '你準備好的type' 不是 '這一個type'

消失在記憶中的code

沒有留言:
KillProcess("EXCEL")


Public Sub KillProcess(ByVal Str_ProcessName As String)
Dim myProcesses() As Process = Process.GetProcesses
Dim procName As String = Str_ProcessName
Dim myProcess As Process
For Each myProcess In myProcesses
If (myProcess.ProcessName.ToLower = procName.ToLower) Then
myProcess.Kill()
End If
Next
End Sub

用字串技巧取檔名和路徑

沒有留言:
CString str;
CString path;
CString FileName;

str = "C:\Program Files\Bonjour\mdnsNSP.dll"  //隨便從硬碟中找一個檔案路徑來試

拆成檔名和路徑:
FileName =  str.Right( str.GetLength() - str.ReverseFind('\\') - 1);
path =  str.Left( str.ReverseFind('\\'));

程式結果:
FileName = mdnsNSP.dll
path = C:\Program Files\Bonjour


合拼起來:
CString filepath;
filepath.Format("%s\\%s", path, FileName);

程式結果:
filepath = C:\Program Files\Bonjour\mdnsNSP.dll

開新檔案/開啓舊檔/存檔/另存新檔,四大天王

沒有留言:

  • 開新檔案  
  • 開啓舊檔 
  • 存檔 
  • 另存新檔

這四個是(SDI或MDI)很常見的程式段。
但是常見到網路上找不到,很多細節又...還是找不到。

所以貼一貼好了!
藍色部份為自己打的code。
黑色部份為系統生成code。
其它色彩為相對應呼叫的結構。

Sample Code:

CString的GetBuffer大小事

沒有留言:
常見的CString在網路上都查得到,所以好用到不用寫筆記。
但是,常常遇到CString::GetBuffer()的疑問就是,它究竟是做什麼的??

CString常用方法簡介
CString::GetString()與CString::GetBuffer()


查了一些參考資料發現

CString::GetBuffer()和CString::ReleaseBuffer()是相對應的動態記憶體宣告與釋放。

CString::GetBuffer()        //先用它取得許多記憶體空間,存放要處理的字串。
CString::ReleaseBuffer()  //存放好之後,再使用它釋放掉多餘不用的記憶體空間。

看到這,你是不是想回去檢查Code看看有沒有什麼地方,是需要釋放釋放的呢?

別急!還有番外篇

CString::GetBufferSetLength()又是做什麼用的?

若上面像是動態記憶體(malloc)的宣告,而這個就像是靜態的宣告(陣列)。
它是無法釋放的。

抓現在目錄之GetModuleFileName()&GetCurrentDirectory()

沒有留言:
執行檔在 D:\Software\App1\SelXls\Debug\SelXls.exe

抓執行檔所在目錄+檔名.exe(因為是執行檔)
GetModuleFileName(NULL, strFilePath.GetBuffer(MAX_PATH+1), MAX_PATH);  //抓應用程式所在的目錄+檔名+副檔名
strFilePath.ReleaseBuffer();   //要加這一行,才可以處理該字串
//      strFilePath = D:\Software\App1\SelXls\Debug\SelXls.exe
        strFilePath = strFilePath.Left(strFilePath.ReverseFind('\\'));    //= D:\Software\App1\SelXls\Debug

抓目前所在目錄(會依開啓舊檔而改變)
GetCurrentDirectory(MAX_PATH, strFilePath.GetBuffer(0));  //抓目前所在的目錄(路徑)
                                                  //      strFilePath = D:\Software\App1\SelXls\Debug


CFileDialog的m_ofn緩充區設定

沒有留言:

MFC的Class,不好用是用過都不喜歡的!就是有很多小地方要注意。
MFC的Class,好用是用過都難以忘記的!就是有很多架構都弄得好好的。
可以說是半成品,所以我就想把所有用過的Class的注意小細節,再包一層Class起來!(算是一個大計劃吧!也許有人做過了!)

這一次是CFileDialog(之前對它的了解,就只是認識這個函數,其它都沒有記錄下來)

    CFileDlg aFileDialog (TRUE, NULL, NULL, OFN_ALLOWMULTISELECT, m_strFilter);

在這樣使用時,總是會有緩充區的問題。
這一次設定了好久,終於弄好了!想說這個code以後要保留下來,所以要把它再包一層下來。

CFileDialog

沒有留言:
CFileDialog fileDlg (
  TRUE, //bOpenFileDialog 設置為 TRUE:開啟舊檔;
                                             //                                 FALSE另存新檔
  "txt", //lpszDefExt 檔案類型的內容
  "*.txt", //lpszFileName 檔案名稱
 OFN_ALLOWMULTISELECT, //dwFlags
 szFilters, //szFilters         瀏覽過濾器
 this //pParentWnd        父視窗指標
//dwSize            預設0:依作業系統預設類型
 );

Sample Code:



void CColorEyeIDoc::OnFileOpen()
{
    CFileDialog aFileDialog (TRUE, NULL, NULL, OFN_SHAREAWARE | OFN_OVERWRITEPROMPT, m_strFilter);
   
    int nID = aFileDialog.DoModal();
    if (nID == IDOK)
    {
        f_Omd->SetMsrData(vChain1);
        if(f_Omd->Open(aFileDialog.GetPathName()))
        {
            SetPathName(aFileDialog.GetPathName());
            SetTitle(aFileDialog.GetFileName());
        }
    }
    UpdateAllViews(NULL);
}



void CColorEyeIDoc::OnFileSaveAs()
{

    CFileDialog fSaveDlg (FALSE, "omd", "*.omd", OFN_SHAREAWARE, m_strFilter);  //存檔會自己加副檔名

    int nID = fSaveDlg.DoModal();
    if (nID == IDOK)
    {
        f_Omd->SetMsrData(vChain1);
        if (f_Omd->Save(fSaveDlg.GetPathName()))
        {
            SetTitle(fSaveDlg.GetFileName());
            SetPathName(fSaveDlg.GetPathName());
        }
           
    }
    DebugByTxt();
}

CFont

沒有留言:
//建立字型的用法
CreateFont(                  m_font.CreateFont(
  int nHeight, 18,                    //指定想要的高度(邏輯單位)的字體。
  int nWidth, 0,                     //指定平均寬度(邏輯單位)中的字符的字體。
  int nEscapement, 0,                     //指定角度(以0.1度為單位),旋轉刻度向量與x軸的夾角。
  int nOrientation, 0,                     //指定角度(以0.1度為單位)之間的字符基線和X軸。
  int nWeight, FW_REGULAR,            //指定字體的粗細(以像素為單位,每簽訂1000)。
  BYTE bItalic, FALSE,                 //指定字體是否斜體。
  BYTE bUnderline, FALSE,                 //指定字體是否下劃線。
  BYTE cStrikeOut, FALSE,                 //指定字體是否加刪除線。
  BYTE nCharSet, SYMBOL_CHARSET,        //指定字集(符號、西歐、BIG5之類的)
  BYTE nOutPrecision, OUT_DEFAULT_PRECIS,    //指定所需的輸出精度。
  BYTE nClipPrecision, CLIP_DEFAULT_PRECIS,   //指定所需的剪切精度。 剪輯精度定義了如何剪輯字符的剪輯區域以外的部分。
  BYTE nQuality, DEFAULT_QUALITY,       //指定字體的輸出質量,它定義如何精心的GDI必須嘗試匹配邏輯字體屬性的一個實際的物理字體。
  BYTE nPitchAndFamily, FIXED_PITCH,           //指定的字距和群組(Family)的字體。
  LPCTSTR lpszFacename "Webdings");           //一個 CString的 或指針為空結束的字符串,指定字體名稱的字體。

CDC活用術

沒有留言:
因為,View想要做得複雜又好維護,用起來像網頁語法一樣順暢
就這樣想

最後設計出來的code如下
void CColorEyeIView::OnDraw(CDC* pDC)
{
    CColorEyeIDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    //表格的部份
    //設計一個table class用類似HTML的語法來管理表格

    //視窗左半邊,導覽區
    CPoint ptTemp = ptFix;

    CTable tbInfo(pDC, ptTemp);
        ptTemp = tbInfo.SetCellNum(2, 4).SetTableBoard(0).SetGridBoard(0).SetFont(afont).SetCellSpace(1)
         .Width(0, TextHight*10).Width(1, TextHight*12).Hight(0, 16).Hight(1, 16).Hight(2, 16)//.Hight(3, 16)
                 .tr().td().b().text("Panel ID").b_().td_()          .td().text(pDoc->GetOmdFile().GetPnlID()).td_().tr_()
                 .tr().td().b().text("Measurement device").b_().td_().td().text(pDoc->GetOmdFile().GetMsrDvc()).td_().tr_()
                 .tr().td().b().text("Probe").b_().td_()             .td().text(pDoc->GetOmdFile().GetPrb()).td_().tr_()
                 .tr().td().b().text("Chanel").b_().td_()            .td().text(pDoc->GetOmdFile().GetCHID()).td_().tr_()
            .table_();
...
}