自定义查找/替换对话框

时间:2011-06-30 18:45:02

标签: c windows winapi

首先,请记住我是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的句柄?

我想指出的是,我在这里感觉有点过头了,所以请说如果我错过了/做错了什么明显的事情。我很确定即使我修复了我遇到的唯一错误,该程序仍然无法正常工作。即使我应该做的事情的概念听起来相当简单,但实际上编程似乎很难:)

这就是上面代码应该做的,最简单的形式:
- 从我想搜索的查找对话框中获取文本 - 从主编辑控件中获取文本
- 从最后一个偏移量进行子字符串搜索(不要每次从头开始)
- 找到结果的位置并重新调整偏移量 - 选择找到的文本

我知道我在这里没有真正问过一个直接的问题,我想直接的问题是:我该怎么做才能做到这一点? :)但更重要的是,了解这是如何工作的。如果你能给我一个精心的答案,我将不胜感激。谢谢你的帮助!

1 个答案:

答案 0 :(得分:1)

看起来你非常接近,你只需要从主窗口获取hwndEdit。您将主窗口的句柄作为父对话框传递给对话框,因此您应该能够获得对话框的父窗口,如下所示:

HWND hwndParent = GetParent(hDlg);

之后,您可以通过引用主窗口定义中的编辑控件ID从该父级获取编辑控件。这样的事情(假设控件ID是IDC_EDIT):

HWND hwndEdit = GetDlgItem(hwndParent, IDC_EDIT);