VS2013 MFC寫dll 多介面 引數傳遞 小雜記
目錄
2. 輸出字串到txt、MessageBox、T2A、_splitpath_s
3. CStringArray的使用、開啟對話方塊將選中的檔名讀出來,允許選擇多個檔案,注意檔名快取
4. 全域性變數的使用 extern包括int 指標 char
11. MFCDlg.cpp中想要不用按鈕建構函式,寫if for做變數運算
1. char[] 轉變 cstring
char fname[];
CString temp(fname);//char轉cstring
2. 輸出字串到txt、MessageBox、T2A、_splitpath_s
MFC中想要輸出字串到txt中,%s,要將char或者string轉變為cstring。
MessageBox輸出提示框,裡面載入文字和變數
T2A的使用
從全路徑獲取檔名 _splitpath_s
USES_CONVERSION;//T2A用的 char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath_s(T2A(strFileName.GetBuffer(0)), drive, dir, fname, ext);//從全路徑中獲取檔名 CString temp2; CString temp(fname);//char轉cstring temp2.Format(_T("計算完畢!\r\n結果儲存在 %s.txt 檔案中!"), temp); MessageBox(temp2);
3. CStringArray的使用、開啟對話方塊將選中的檔名讀出來,允許選擇多個檔案,注意檔名快取
CStringArray wet_type;
wet_type.Add(_T("mangr"));
wet_type.Add(_T("hekou"));
wet_type.Add(_T("resh"));
CString name1 = FileName1.GetAt(i);//直接拿出來,就可以%s,name1
CString temp2;
temp2.Format(_T("計算完畢!\r\n結果儲存在 %s.txt 檔案中!"), name1 );
將選中的檔名讀出來
//將選中的檔名讀出來
CFileDialog dlgFile(TRUE, _T("shp"), NULL,
OFN_EXPLORER, _T("(向量檔案)|*.shp")); //建立開啟檔案對話方塊
dlgFile.m_ofn.Flags |= OFN_ALLOWMULTISELECT;//允許選擇多個檔案
//設定一個檔名快取,因為CFileDialog內建的檔名快取長度只有200,但是很多時候,檔案的路徑遠大於這個數,為了保險起見,所以要自己設定一個檔名快取
dlgFile.m_ofn.lpstrFile = new TCHAR[500];
memset(dlgFile.m_ofn.lpstrFile, 0, 500);
//設定快取長度
dlgFile.m_ofn.nMaxFile = 500;
if (dlgFile.DoModal() == IDOK){
CString strPathName = dlgFile.GetPathName();//獲取檔案路徑到strPathName
m_file.SetWindowText(strPathName);//顯示檔案路徑到編輯框
POSITION pos_file;
pos_file = dlgFile.GetStartPosition();//獲得初試位置,如果不設定檔名快取[預設200],如果檔名過長,會報錯
CStringArray ary_filename1;
while (pos_file != NULL){
pathName1 = dlgFile.GetNextPathName(pos_file);
ary_filename1.Add(pathName1);
}
CString strTmp = ary_filename1.GetAt(i);
char* filepath1 = T2A(strTmp.GetBuffer(0));//Cstring轉變char*
...
4. 全域性變數的使用 extern包括int 指標 char
首先在Dlg.h的extern宣告
extern int count1;
extern int count2 ;
extern int count3;
extern double* Area1;
extern double* Area2;
extern double* Area3;
//用於儲存13個溼地型別
//分別對應的是 紅樹林、河口水域、海岸性淡水湖、海岸性鹹水湖、庫塘、內陸河流、內陸湖泊、
//其他水體、淺海水域、沙石海灘、岩石海灘、養殖場、淤泥質海灘
extern int index1[];
extern int index2[];
extern int index3[];
//儲存年份用
extern char year1[];
extern char year2[];
extern char year3[];
然後在Dlg.cpp中定義
//儲存所選溼地型別個數
int count1 = 0;
int count2 = 0;
int count3 = 0;
double* Area1 = NULL;
double* Area2 = NULL;
double* Area3 = NULL;
//
char year1[50];
char year2[50];
char year3[50];
//預設是666
int index1[13] = {666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666};
int index2[13] = {666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666};
int index3[13] = {666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666};
最後在Dlg2.cpp或者其他的cpp檔案中,引入 #include "Dlg.h" 即可
5. vector模板類的使用、string變char
vector<string> filename1;
//
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath_s(T2A(strTmp.GetBuffer(0)), drive, dir, fname, ext);//從全路徑中獲取檔名
//
size_t len = strlen(fname);
filename1.push_back(fname);
string變char,將20160807_wet.shp提取出2016年份,返回,注意最後'\0'
char year1[100];
int bj;
for (bj = 0; bj < 4; bj++)
{
year1[bj] = filename1[0][bj];
}
year1[bj] = '\0';
6. 將按鈕返回路徑給編輯框
首先,給編輯框新增變數
7. MFC呼叫帶MFC介面的DLL,以及傳遞引數
https://blog.csdn.net/hanford/article/details/53633870很全的
只適用於以下的方法:注意傳遞的時候,不能直接傳送模板類比如vector,且輸出必定是指定個數,【目前的理解,比如動態建立的東西就不行】必須要例項化裡面的函式,然後輸出這個函式
dll檔案建立:
類名:CWetland_Extraction_MFCDlg
標頭檔案:Wetland_Extraction_MFCDlg.h、export_variable.h
cpp:Wetland_Extraction_MFCDlg.cpp
1) 在Wetland_Extraction_MFCDlg.cpp檔案中最下面新增:
extern "C" __declspec(dllexport) void ShowDlg(void)
{
// 此處需要加下面這行程式碼,不然對話方塊顯示不出來。
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CTEST_MFC_DLLDlg dlg;
dlg.DoModal();//實現DLL資源切換的?AFX_MANAGE_STATE(AfxGetStaticModuleState());
}
2)export_variable.h新增:
#pragma once //只編譯一次
__declspec(dllexport) int A = 300;
__declspec(dllexport) int B[4] = { 1,2,3,4 };
dll檔案引用:
1) 建立一個新的工程,然後建立import_variable.h
#pragma comment(lib, "../debug/TEST_MFC_DLL.lib")
HINSTANCE hDll = LoadLibrary(_T("TEST_MFC_DLL.dll"));
__declspec(dllimport) int A;
__declspec(dllimport) int B[4];
2) 在dlgcpp按鈕函式下加入,就可以彈出介面了
typedef void(*lpFun)(void);
if (NULL == hDll)
{
MessageBox(L"載入失敗");
}
lpFun pShowDlg = (lpFun)GetProcAddress(hDll, "ShowDlg");
if (pShowDlg == NULL)
{
MessageBox(L"載入失敗");
}
pShowDlg();
8. MFC下建立類似ENVI經典介面的程式
昨天想建一個類似ENVI介面的程式,然後就在網上搜了一下,也沒有什麼好的方法,後來就自己摸索,先將自己寫程式碼的過程經驗記錄下來以供大家分享啊。
首先,我用的是VS2010其他的應該觸類旁通,1)建立基於對話方塊類的MFC專案。然後相應修改對話方塊的外觀,在對話方塊屬性外觀欄中將Border值修改為Thin(這樣即實現了禁止通過滑鼠拖拽修改對話方塊大小)如圖所示
2)其次,在資源檢視下任意一個資料夾下右擊選擇新增資源選擇Menu項新增選單,如圖所示
然後便可以在選單欄中新增你想要的命令與程式碼
3)最後將選單加入到對話方塊中即大功告成,在對話方塊的屬性列表的雜項中Menu一項選擇你建好的選單即可
編譯執行效果如下圖
9. LPSTR轉char*
char *year1;
CString year1_temp = pstrData[1].Left(4);//取前四位 eg.2016
year1 = (char*)year1_temp.GetBuffer();//lpstr轉換char*
10. CString擷取字元
如果沒有中文可以直接:cstring a;a.left(4);取前四個字元
如果有中文,我的辦法是新建char a[5]
從2014年溼地,中提取2014出來
CString year1_temp;
year1_temp = pstrData[1];
int bj;
for (bj = 0; bj < 4; bj++)
{
year1[bj] = year1_temp[bj];//cstring可以直接用下標[]
}
year1[bj] = '\0';//注意最後的'\0'
11. MFCDlg.cpp中想要不用按鈕建構函式,寫if for做變數運算
int count1 = 0;
int count2 = 0;
double Area1[13];
double Area2[13];
char year1[15];
char year2[15];
void Statistical_Data_VisualizationDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TCHART3, m_chart_new);
count1 = 13;
count2 = 13;
CStdioFile file;
CString strLine;
if (!file.Open(_T("g:\\log.csv"), CFile::modeRead))
{
AfxMessageBox(_T("請先進行各類溼地變化檢測模組"));
return;
}
int n = 0;
file.ReadString(strLine);
CString *pstrData = SplitString(strLine, ',', n);
//取前四位 eg.2016
int bj;
for (bj = 0; bj < 4; bj++)
{
year1[bj] = pstrData[1][bj];
year2[bj] = pstrData[2][bj];
}
year1[bj] = '\0';
year2[bj] = '\0';
for (int i = 0; i < 13; i++)
{
file.ReadString(strLine);// 讀取下一行
CString *pstrData = SplitString(strLine, ',', n);
Area1[i] = _ttof(pstrData[1]);
Area2[i] = _ttof(pstrData[2]);
}
}
12. 自定義分割函式(可用於讀取csv檔案)
首先可以在Dlg.h中宣告,動態建立,用到指標*
class Statistical_Data_VisualizationDlg : public CDialogEx
{
......
//因為不知道返回多少個CString,涉及到動態建立,所有要用*
public:
CString* SplitString(CString str, char split, int iSubStrs); //分割字串
}
然後在Dlg.cpp中定義
CString* Statistical_Data_VisualizationDlg::SplitString(CString str, char split, int iSubStrs)
{
int iPos = 0; //分割符位置
int iNums = 0; //分割符的總數
CString strTemp = str;
CString strRight;
//先計運算元字串的數量
while (iPos != -1)
{
iPos = strTemp.Find(split);
if (iPos == -1)
{
break;
}
strRight = strTemp.Mid(iPos + 1, str.GetLength());
strTemp = strRight;
iNums++;
}
if (iNums == 0) //沒有找到分割符
{
//子字串數就是字串本身
iSubStrs = 1;
return NULL;
}
//子字串陣列
iSubStrs = iNums + 1; //子串的數量= 分割符數量+ 1
CString* pStrSplit;
pStrSplit = new CString[iSubStrs];
strTemp = str;
CString strLeft;
for (int i = 0; i < iNums; i++)
{
iPos = strTemp.Find(split);
//左子串
strLeft = strTemp.Left(iPos);
//右子串
strRight = strTemp.Mid(iPos + 1, strTemp.GetLength());
strTemp = strRight;
pStrSplit[i] = strLeft;
}
pStrSplit[iNums] = strTemp;
return pStrSplit;
}
使用
CString strLine;
int n = 0;
for (int i = 0; i < 13; i++)
{
file.ReadString(strLine);// 讀取下一行
CString *pstrData = SplitString(strLine, ',', n);
Area1[i] = _ttof(pstrData[0]);//CString轉換成double
Area2[i] = _ttof(pstrData[1]);//CString轉換成double
}
13. 獲取當前解決方案的debug路徑
WCHAR szPaht[MAX_PATH] = { 0 };
GetModuleFileName(NULL, szPaht, sizeof(szPaht));//獲取exe的路徑
PathRemoveFileSpec(szPaht);
// 設定你的檔名
CString strFileName3("Demo.txt");
// 將檔名附加在 當前路徑 裡面
wcscat_s(szPaht, L"\\"); ///知道為啥是L 開頭嗎,因為vs2013工程預設是unicode環境,unicode字串需要 L 開頭的巨集
wcscat_s(szPaht, strFileName3.GetString());//這時候szPaht已經是全路徑了
//如果原來存在就刪除檔案
if (PathFileExists(szPaht))
{
DeleteFile(szPaht);
}
/// 必須 設定 一下 語言環境,否則 my_log_file.WriteString 不能輸出中文(是不是感覺好複雜?)沒關係,當前工程能跑起來,能夠就行。
//setlocale(LC_ALL, "chs");
// 檔案讀寫 StdioFile
// 1.建立 CStdioFile的物件,並指定 讀寫檔案的方式。 CFile::modeNoTruncate,不會覆蓋之前的檔案。
CStdioFile my_log_file(szPaht, CFile::modeWrite | CFile::modeCreate | CFile::modeNoTruncate);
/// 這裡將2行程式碼合併為1行了。如果分開寫,是這樣的:
/// CStdioFile my_log_file;
/// my_log_file.Open(szPaht, CFile::modeWrite | CFile::modeCreate | CFile::modeNoTruncate);
// 2.將讀寫指標移到檔案末尾
my_log_file.SeekToEnd();
CString strData;
strData.Format(L"%s\n", strPathName1);
my_log_file.WriteString(strData);
strData.Format(L"%s\n", strPathName2);
my_log_file.WriteString(strData);
// 4.關閉 讀寫指標
my_log_file.Close();