首先,请记住我是Windows编程的新手。我会尽量详细地讨论我的问题,所以希望答案也是如此。
我是复制使用Win32 API和纯C编写类似记事本的应用程序。对于那些熟悉Petzold Windows编程的人来说,这是他过去常用的POPPAD程序的修改版本描述通用对话框。我这样做是出于教育目的,所以请不要发表评论,例如“为什么要使用旧技术,使用.NET”,因为这些评论无法帮我解决问题:)。
Petzold在他的POPPAD程序中使用Common Dialog Boxes来编写类似Notepad的应用程序。他使用Edit Control来提供基本文本编辑器的所有功能。 POPPAD,就像一个记事本,也有查找和替换对话框,你可以找到东西并替换它!我知道,令人难以置信。
所以这是我想通过阅读过去章节来测试我新获得的知识的地方,因为我决定编写我自己的“查找和替换”对话框。当然,它可能是最简单的形式。它能有多难?你有一个文本字段,你输入一些文字,你有一个花哨的按钮,上面写着“查找!”在它上面 现在我想再次提醒你,我是Windows编程的新手,请原谅任何可能的新手问题。此外,我想指出,我将专注于使“查找”对话框正常工作,因为“替换”不应该太难实现。
所以我在Visual Studio中使用资源编辑器,几个小时后我得到了这个:
(stackoverflow实际上不允许我发布图像,所以这里是下面的链接)
http://i.imgur.com/R98x4.png
我将此对话框命名为“查找”(带引号),因此我不必在我的程序中使用MAKEINTRESOURCE
宏,就像Petzold的思想学派一样。我将“确定”按钮的标题更改为“查找下一个”,并将其ID从IDOK
更改为IDC_FIND
。还将IDCANCEL
更改为IDC_CANCEL
,单行编辑控件为IDC_FIND_FIND
。
现在更严肃的事情。在我的主程序的Windows程序中,我有这段代码:
case IDM_SEARCH_FIND:
hDlgModeless = CreateDialog (hInst, TEXT ("Find"),
hwnd, FindDlgProc) ;
return 0 ;
IDM_SEARCH_FIND
是菜单项的消息标识符,单击该属性时应打开“查找”对话框。 CreateDialog函数用于创建无模式对话框,并将其句柄存储到全局变量hDlgModeless
中。 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
的句柄?
我想指出的是,我在这里感觉有点过头了,所以请说如果我错过了/做错了什么明显的事情。我很确定即使我修复了我遇到的唯一错误,该程序仍然无法正常工作。即使我应该做的事情的概念听起来相当简单,但实际上编程似乎很难:)
这就是上面代码应该做的,最简单的形式:
- 从我想搜索的查找对话框中获取文本
- 从主编辑控件中获取文本
- 从最后一个偏移量进行子字符串搜索(不要每次从头开始)
- 找到结果的位置并重新调整偏移量
- 选择找到的文本
我知道我在这里没有真正问过一个直接的问题,我想直接的问题是:我该怎么做才能做到这一点? :)但更重要的是,了解这是如何工作的。如果你能给我一个精心的答案,我将不胜感激。谢谢你的帮助!
答案 0 :(得分:1)
看起来你非常接近,你只需要从主窗口获取hwndEdit。您将主窗口的句柄作为父对话框传递给对话框,因此您应该能够获得对话框的父窗口,如下所示:
HWND hwndParent = GetParent(hDlg);
之后,您可以通过引用主窗口定义中的编辑控件ID从该父级获取编辑控件。这样的事情(假设控件ID是IDC_EDIT):
HWND hwndEdit = GetDlgItem(hwndParent, IDC_EDIT);