TabCtrl_GetItem宏未按预期工作

TabCtrl_GetItem macro not working as expected

本文关键字:工作 GetItem TabCtrl      更新时间:2023-10-16

我正在创建一个基本的记事本程序,当用户单击关闭时,我希望它询问用户是否要保存打开的当前文档。我使用了一个选项卡式界面,并试图检索文件名(选项卡上的文本),所以我有一个MessageBox,上面写着"你想保存吗:无标题.txt"或类似的内容。我在获取文件名时遇到问题。这就是我目前拥有的:

case ID_FILE_CLOSE:  // When the close button is clicked
  {
    HWND hEdit, hTabs;
    hTabs = GetDlgItem( hwnd, IDC_MAIN_TAB );
    int curTab = TabCtrl_GetCurSel( hTabs );
    TCITEM curtitem;
    TabCtrl_GetItem( hTabs, curTab, &curtitem );
    // Check for file name
    MessageBox( hwnd, curtitem.pszText, "Test", MB_OK );
  }
  break;

这是我一直在弹出框中得到的错误,其中有"中断"、"继续"、"忽略"按钮:

notepadremium.exe中0x7597d298处未处理的异常:0xC0000005:读取位置0xcccccccc时发生访问冲突。

我使用的是MS Visual C++Express 2010。

我还有一个包含文件名的列表框,其中还显示了扩展名(几乎像notepad++文档切换器),并通过一条消息尝试了LB_GETITEMDATA,但总是返回空白。我想这是因为我使用LB_ADDSTRING将其添加到列表框中。(列表框和选项卡是相互连接的,当您单击列表框中的文件时,它会变为相应的选项卡)。为什么我的代码不能正常工作?

阅读文档:

坑类型:LPTCITEM

指向TCITEM结构的指针,该结构指定要检索的信息并接收有关选项卡的信息。发送消息时,掩码成员指定要返回的属性。如果掩码成员指定了TCIF_TEXT值,则pszText成员必须包含接收项文本的缓冲区的地址,cchTextMax成员必须指定缓冲区的大小

您根本没有初始化TCITEM。您需要告诉TabCtrl_GetItem()要检索什么数据,更重要的是,您提供了什么缓冲区来接收数据。您没有执行任何操作,而是将随机数据传递给TabCtrl_GetItem(),这就是它崩溃的原因。

试试这个:

case ID_FILE_CLOSE:  // When the close button is clicked
  {
    HWND hTabs = GetDlgItem( hwnd, IDC_MAIN_TAB );
    int curTab = TabCtrl_GetCurSel( hTabs );
    TCHAR szFileName[MAX_PATH+1] = {0};
    TCITEM curtitem = {0};
    curitem.mask = TCIF_TEXT;
    curitem.pszText = szFileName;
    curitem.cchTextMax = MAX_PATH;
    if (TabCtrl_GetItem( hTabs, curTab, &curtitem ))
    {
      // also from the documentation:
      //
      // "the control may change the pszText member of the structure
      // to point to the new text instead of filling the buffer with
      // the requested text. The control may set the pszText member
      // to NULL to indicate that no text is associated with the item."
      //
      // which means you cannot rely on the szFileName[] buffer actually
      // containing the filename, you have to use whatever buffer the
      // TCITEM is actually pointing at, which may or may not be the
      // szFileName buffer...
      MessageBox( hwnd, curitem.pszText, TEXT("Test"), MB_OK );
    }
  }
  break;

至于您的ListBox问题,您说您使用LB_ADDSTRING向ListBox添加字符串,但使用LB_GETITEMDATA检索字符串。这是错误的。您需要使用LB_GETTEXTLENLB_GETTEXTLB_GETITEMDATA用于检索使用LB_SETITEMDATA添加到ListBox的用户定义数据。