首先,请记住我是Windows编程的新手。 我会尽量详细地回答我的问题,希望答案也是如此。
我正在复制使用Win32 API和纯C编写类似于记事本的应用程序。对于熟悉Petzold的Windows编程的人员,这是他用来描述通用对话框的POPPAD程序的修改版本。 我正在为了教育目的而严格地写这篇文章,所以请不要发表评论,比如“为什么你使用旧技术,使用.NET”,因为那些评论不会帮我解决我的问题:)。
Petzold在他的POPPAD程序中使用通用对话框来编写这个类似于记事本的应用程序。 他使用编辑控制来提供基本文本编辑器的所有function。 POPPAD就像一个记事本,也有查找和replace对话框,你可以find东西并replace它! 令人难以置信,我知道。
所以这就是我想通过阅读过去的章节来testing我新近获得的知识的地方,因为我决定写我自己的查找和replace对话框。 当然,这可能是最简单的forms。 它能有多难? 你有一个文本字段,你input一些文本,你有一个奇特的button,说:“查找! 在上面。
现在我想再次提醒您,我是Windows编程的新手,所以请原谅我的任何可能的新手问题。 此外,我想指出,我将专注于使查找对话框工作,因为replace应该不太难实现。
所以我在Visual Studio中使用了资源编辑器,几个小时后,我得到了这个:
(stackoverflow实际上并不允许我发布图像,所以下面的链接)
http://img.zgserver.com/c/R98x4.png
我将这个对话框命名为“Find”(带引号),所以我不必在我的程序中使用MAKEINTRESOURCE
macros,就像Petzold的学派一样。 我将“确定”button的标题更改为“查找下一个”,并将ID从IDOK
更改为IDC_FIND
。 IDC_CANCEL
IDCANCEL
更改为IDC_CANCEL
,单行Edit Control为IDC_FIND_FIND
。
现在到更严重的事情。 在我的主程序的Windows程序中,我有这样一段代码:
case IDM_SEARCH_FIND: hDlgModeless = CreateDialog (hInst, TEXT ("Find"), hwnd, FindDlgProc) ; return 0 ;
IDM_SEARCH_FIND
是菜单项的消息标识符,单击时应打开“查找”对话框。 CreateDialog函数用于创build一个无模式对话框并将其句柄存储到全局variableshDlgModeless
。 FindDlgProc
是对话框程序的名称,我认为所有的代码都是查找文本的。
所以,不用再烦恼了,下面是我的查找对话框过程的代码:
BOOL CALLBACK FindDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static TCHAR szFindWhat[MAX_STRING_LEN]; //Text to find static int iOffset ; //Offset from the beginning of Edit control to the result int iLength, iPos, iSingleLength ; //Length of a main Edit control and single line Edit control PTSTR pstrDoc, pstrPos ; switch (message) { case WM_INITDIALOG: return TRUE ; case WM_COMMAND: switch (LOWORD (wParam)) { //If the button "Find Next" has been pressed, process all the logic of finding the text case IDC_FIND: // Get the text from a single-line edit control in Find dialog box // and save it in szFindWhat variable iSingleLength = GetWindowTextLength(GetDlgItem(hDlg, IDE_FIND_FIND)) ; GetWindowText(GetDlgItem(hDlg, IDE_FIND_FIND), szFindWhat, iSingleLength) ; // Get the text from a main Edit control, allocate memory for it // and store it in pstrDoc variable iLength = GetWindowTextLength (hwndEdit) ; if (NULL == (pstrDoc = (PTSTR) malloc ((iLength + 1) * sizeof (TCHAR)))) return FALSE ; GetWindowText (hwndEdit, pstrDoc, iLength + 1) ; // Search the document for the find string pstrPos = _tcsstr (pstrDoc + iOffset, szFindWhat) ; free (pstrDoc) ; // Return an error code if the string cannot be found if (pstrPos == NULL) return FALSE ; // Find the position in the document and the new start offset iPos = pstrPos - pstrDoc ; iOffset = iPos + lstrlen (szFindWhat) ; // Select the found text SendMessage (hwndEdit, EM_SETSEL, iPos, iOffset) ; SendMessage (hwndEdit, EM_SCROLLCARET, 0, 0) ; case IDC_CANCEL: DestroyWindow (hDlg) ; hDlgModeless = NULL ; break ; } break ; case WM_CLOSE: DestroyWindow (hDlg) ; hDlgModeless = NULL ; break ; default: return FALSE; } return FALSE ; }
我得到的唯一的实际错误是hwndEdit
是未声明的标识符。 hwndEdit
是主要的Edit控件(不是Find对话框中的单行)。 在查找对话框过程中,如何获取hwndEdit
的句柄?
我想指出的是,我现在感觉有些过头了,所以请说出是否我错过了/做错了一些明显的事情。 我很确定,即使我修复了唯一的错误,程序仍然无法正常工作。 即使我应该做什么的概念听起来相当简单,实际上编程似乎相当困难:)
这就是上面的代码应该做的最简单的forms:
– 从我希望search的查找对话框中获取文本
– 从主编辑控件获取文本
– 从最后一个偏移量开始进行子stringsearch(不要每次都从头开始)
– find结果的位置并重新调整偏移
– selectfind的文本
我知道我并没有在这里直接提出问题,我想直接的问题是:我该如何做这项工作? :)但更重要的是要了解这是如何工作的。 如果你能给我一个详尽的答案,我将不胜感激。 感谢所有的帮助!
看起来你非常接近,你只需要从你的主窗口获得hwndEdit。 您将父窗口的句柄作为父窗口传递给您的对话框,因此您应该能够像这样获取对话框的父窗口:
HWND hwndParent = GetParent(hDlg);
之后,通过引用主窗口定义中的编辑控件ID,可以从该父项获得编辑控件。 像这样(假设控制ID是IDC_EDIT):
HWND hwndEdit = GetDlgItem(hwndParent, IDC_EDIT);