【弹出对话框】
1,添加对话框。
要想弹出对话框,首先肯定要先新建一个对话框。这里默认你已经建立了主MFC的情况,这样才会在解决方案资源管理器那边有【资源视图】这一选项卡。
【资源视图】——【Dialog】——右键【insert dialog】
一个dialog新建完毕。
2,为dialog添加对应的类
右击【dialog】——【添加类】——输入类名(假设为 A)点击确定
完成这两步,一个对话框就能被调用了。
3,弹出对话框
例如需要点击主对话框的确定按钮弹出上述dialog,那么双击【确定】按钮,或右击【确定】添加单击的消息响应函数。
在其中添加:
A a;
a.DoModal();
这里DoModal是以【模态对话框】形式展现,即这个对话框弹出后别的对话框不能使用直到当前对话框关闭。
需要注意的是,新建对话框时,默认有确定和取消两个按钮的,它们的ID默认为IDOK和IDCancel,DoModal函数返回值为可以为这两个ID,表示点击了某个按钮。例如:
INT_PTR flag = a.DoModal();
if (flag == IDOK)
{...}
====================================================================
【对其控件进行操作】
最头疼的是如何对子对话框的控件进行操作。这里用【如何在主程序中获得子窗口编辑框中键盘键入的数据】为例。
1,首先肯定要给这个eidtBox关联一个变量。
右击dialog中的编辑框控件,添加变量,假设为g_getName。
做完这一步,在A.cpp中的DoDataExchange函数中已经自动将变量和编辑框的ID关联起来了。
【但是,这并不代表输入编辑框的值会自动赋给getName变量,也就是说,DoDataExchange函数不会自动执行】
2.编辑框变量值g_getName能够响应用户用键盘输入的值
之前我还费尽心思添加一个OnInitDialog虚函数,并在虚函数里采用
bool get_peopleid::oninitdialog() { cdialogex::oninitdialog(); // todo: 在此添加额外的初始化 char id_num[20] = { 0 }; cstring str; str= _t(""); str.format(_t("gfdgh")); g_getname.setwindowtext(str); updatedata(true); g_getname.getwindowtext(str); return TRUE; }
类似这种方法,希望能够利用updatedata函数来更新编辑框的变量值。然并卵,除了能初始化显示gfdfh在对话框中之外,其他都行不通。
后来看了这篇文章http://wenku.baidu.com/view/04a27d6a561252d380eb6e49.html。想起,此处只要相应一个消息函数即可。
//sample代码,下面还会说到 void get_PeopleID::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码 CString str; g_getName.GetWindowText(str); std::cout << str << std::endl; //a AfxMessageBox(str); //b CDialogEx::OnOK(); }
这样str就是你输入的值啦。
3,获取编辑框的值
a,句柄说(获取子对话框空间值,反正我是行不通)
char id_num[10]=""; SendMessageA(h, WM_GETTEXT, sizeof(id_num), LPARAM(id_num));
据说这样可以将h句柄的值读入id_num中,所以我们只要找到编辑框的句柄值就好了嘛。
网上有好几种方法获取句柄,代表性的为:
a.1 GetDlgItem函数, h= GetDlgItem(getName)->GetSafeHwnd();
然而,这样得出的id_num是主MFC中编辑框的值。是的,虽然我填的是子对话框editBox的ID,但是得出的仍然是主对话框的值。 GetDlgItem()函数是不能获取子对话框的句柄的。
a.2 spy++
据说,【工具】中有个spy的东东可以查看控件的句柄,而且可视化,点哪显示哪,试一下(自行百度spy的用法),果然名不虚传。But,
HWND h = (HWND)0x000003ed;//手工spy查到的editBox的句柄值
SendMessageA(h, WM_GETTEXT, sizeof(id_num), LPARAM(id_num));
显示的结果是 id_num的空,多试几次后发现每次的h值都不一样,原来每次程序都会分配新的句柄值嘛!所以怎么能用上一次的值来查找这次的句柄呢~
a.3 FindWindowEx函数
HWND hWnd = ::GetForegroundWindow();
HWND handle1 = ::FindWindowEx(hWnd, 0, NULL, "getName"); //handle1=00000
先找到当前窗口的句柄值,各种窗口的句柄值获取请参照:http://my.oschina.net/u/2314763/blog/422622?fromerr=SobXFhyw
然而事实证明还是不能显示
a.4 既然在主函数中总是获取不到子对话框控件的句柄值,那我在A.cpp中设置好返回总可以吧。
// A.cpp char* get_PeopleID::get_handle() { char id_num[10] = ""; SendMessageA(g_getName.m_hWnd, WM_GETTEXT, sizeof(id_num), LPARAM(id_num)); //g_getName.m_hWnd直接获取控件句柄 std::cout << id_num << std::endl; return id_num; }
调用get_handle之前我有在单击确定按钮中加入g_getName.GetWindowText(str);将对话框的值与变量连接。在main.cpp中先点击确定执行此处,在调用get_handle,想返回id_num,无果。依然为空。
b,GetWindowText及CString to char* 的转换
上述sample代码中已经已经获取到了输入的值,并保存在str(可以设置为A的全局变量,方便在其他类中获取)中,但是如果不采用AfxMessageBox,在std中看到的类似于地址的输出,这是怎回事呢?原来CString用cout输出的是str地址
如果你单纯的要显示在控制台中,只需要printf(“%S”,str)即可,注意S大写。
但是如果你之后还要用,需要进行转换,例如转换成char*,可以参照博文http://blog.163.com/ming__nan/blog/static/6783288200991111281852/
此处将最有效代码直接贴出,网上其他的什么强制转换经实验大部分都是扯淡。
// CString str to char* c int len = WideCharToMultiByte(CP_ACP, 0,str, -1, NULL, 0, NULL, NULL);//Cstring To char * in Unicode character set char* c = new char[len + 1]; WideCharToMultiByte(CP_ACP, 0, str, -1, c, len, NULL, NULL);