TabCtrl_GetItem宏未按预期工作

时间:2013-11-19 20:08:03

标签: c++ winapi tabbed-interface

我正在创建一个基本的记事本程序,当用户点击关闭时,我希望它询问用户是否要保存当前打开的文档。我正在使用选项卡式界面,并尝试检索文件名(选项卡上的文本),因此我有一个MessageBox,上面写着“你想保存:untitled.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;

这是我在一个带有Break,Continue,Ignore按钮的弹出框中的错误:

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

我正在使用MS Visual C ++ Express 2010。

我还有一个列表框,其文件名也显示扩展名(几乎像记事本++文档切换器)并通过消息尝试LB_GETITEMDATA,但总是返回空白。我认为这是因为我使用LB_ADDSTRING将其添加到列表框中。 (列表框和选项卡是互连的,当您单击列表框中的文件时,它将更改为相应的选项卡)。为什么我的代码不按照应有的方式工作?

1 个答案:

答案 0 :(得分:3)

Read the documentation

  

pitem   键入: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_GETTEXT代替。 LB_GETITEMDATA用于检索使用LB_SETITEMDATA添加到ListBox的用户定义数据。