【发布时间】:2021-11-15 17:08:15
【问题描述】:
目前我正在尝试测试 IAutoComplete COM 接口,这需要我使用 MSVC cpp 编译器。我面临着一个我在 MingGW 从未遇到过的问题。 MSVC 看到我的 throw 语句并完全忽略它。所以不知道有没有我没设置的设置。
好吧,我投了反对票,因为我举了一个不好的例子,这可能是我应得的。我认为它未能抛出,因为它在一个结构中,但尝试使用新的结构证明我错了。我可能无法提供可重现的示例,但我会尝试。
准备大量代码。
Jav/AutoObject.h
#ifndef JAV_WIN32_AUTO_OBJECT_HPP
#define JAV_WIN32_AUTO_OBJECT_HPP
#include <Jav/config.h>
namespace Jav
{
struct AutoObject
{
virtual ~AutoObject(){}
void* operator new(size_t sz);
};
AutoObject* shallowCopy(AutoObject*);
AutoObject* deleteObject(AutoObject*);
}
#endif // JAV_WIN32_AUTO_OBJECT_HPP
Jav/win32/widgets/widgets_ex.h
#ifndef JAV_WIN32_GUI_WIDGETS_EX_HPP
#define JAV_WIN32_GUI_WIDGETS_EX_HPP
#include <Jav/win32/widgets/widgets.h>
namespace Jav { namespace win32 {
class Widget
{
public:
Widget(HWND widget=nullptr) : widget(widget){}
operator HWND() { return widget; }
public:
void setId(int id) { SetWindowLong(widget,GWLP_ID,id); }
void destroy() { DestroyWindow(widget); widget = NULL; }
void show() { ShowWindow(widget,SW_SHOW); }
void hide() { ShowWindow(widget,SW_HIDE); }
protected:
HWND widget;
};
}}
#endif // JAV_WIN32_GUI_WIDGETS_EX_HPP
Jav/win32/window/Window.h
#include <Jav/win32/widgets/widgets_ex.h>
using Window = Widget;
Jav/win32/window/SimpleWindow.h
#ifndef JAV_WIN32_WINDOW_SIMPLE_WINDOW_HPP
#define JAV_WIN32_WINDOW_SIMPLE_WINDOW_HPP
#include <Jav/AutoObject.h>
#include <Jav/win32/window/Window.h>
namespace Jav { namespace win32 {
struct Content__ : AutoObject
{
virtual void onCreate(HWND,CREATESTRUCTA*) {}
virtual void onDestroy() {}
virtual void onSize(int w,int h) {}
virtual void onDraw(Canvas&) {}
};
class SimpleWindow : public Window
{
public:
SimpleWindow(Content__*, const char *title, size_t w,size_t h,
int style=WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
int ex_style=0);
public:
bool isOpen();
void close();
const MSG& getMessage();
const MSG& peekMessage();
void dispatchMessage(const MSG&);
private:
static ATOM registerWindow();
static LRESULT CALLBACK windowProc(HWND,UINT,WPARAM,LPARAM);
static HWND createWindow(Content__*, const char *,HMENU, size_t,size_t, int,int);
private:
MSG msg;
};
}}
#endif // JAV_WIN32_WINDOW_SIMPLE_WINDOW_HPP
AutoObject.cpp
#include <Jav/AutoObject.h>
#include <unordered_map>
#include <objbase.h>
namespace {
struct AutoObjectsMap : std::unordered_map<Jav::AutoObject*,size_t>
{
~AutoObjectsMap() { for(auto &obj : *this) CoTaskMemFree(obj.first); }
};
AutoObjectsMap *alloc_objects_ptr;
struct AutoObjectsMapMgr
{
~AutoObjectsMapMgr() { delete alloc_objects_ptr; };
};
}
#define alloc_objects (*alloc_objects_ptr)
namespace Jav
{
void* AutoObject::operator new(size_t sz)
{
auto mem = CoTaskMemAlloc(sz);
if(!alloc_objects_ptr) alloc_objects_ptr = new AutoObjectsMap();
alloc_objects[(AutoObject*)mem] = 1;
return mem;
}
AutoObject* shallowCopy(AutoObject *r)
{
auto elem = alloc_objects.find(r);
if( elem != alloc_objects.end() ) ++alloc_objects[r];
return r;
}
AutoObject* deleteObject(AutoObject *mem)
{
auto elem = alloc_objects.find(mem);
if( elem != alloc_objects.end() )
{
if(--elem->second == 0)
{
mem->~AutoObject();
CoTaskMemFree(mem);
alloc_objects.erase(elem);
return nullptr;
}
}
return mem;
}
}
SimpleWindow.cpp
#include <Jav/win32/window/SimpleWindow.h>
namespace Jav { namespace win32 {
namespace {
LRESULT CALLBACK SimpleWindow::windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Content__ *obj = (Content__*)GetWindowLongPtrA(hwnd,GWLP_USERDATA);
auto getWidth = [lParam](){ return LOWORD(lParam); };
auto getHeight = [lParam](){ return HIWORD(lParam); };
auto getX = [lParam](){ return LOWORD(lParam); };
auto getY = [lParam](){ return HIWORD(lParam); };
auto getWidget = [lParam](){ return (HWND)lParam; };
auto widgetId = [wParam](){ return LOWORD(wParam); };
auto widgetEvent = [wParam](){ return HIWORD(wParam); };
auto menuType = [wParam](){ return LOWORD(wParam); };
auto eventId = [wParam](){ return LOWORD(wParam); };
switch (uMsg)
{
case WM_CREATE:
{
CREATESTRUCT *cs = ((CREATESTRUCTA*)lParam);
obj = (Content__*)cs->lpCreateParams;
SetWindowLongPtr(hwnd,GWLP_USERDATA,(LONG_PTR)obj);
obj->onCreate(hwnd,cs);
return 0;
}
case WM_DESTROY:
obj->onDestroy();
deleteObject(obj);
return 0;
case WM_SIZE:
obj->onSize(getWidth(),getHeight());
return 0;
default: return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
ATOM SimpleWindow::registerWindow()
{
WNDCLASSEX wincl = {};
wincl.cbSize = sizeof(WNDCLASSEX);
wincl.lpszClassName = "JavWin32WindowSimpleWindow";
wincl.lpfnWndProc = SimpleWindow::windowProc;
wincl.style = CS_HREDRAW|CS_VREDRAW;
wincl.hIcon = LoadIcon(NULL,IDI_APPLICATION);;
wincl.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
wincl.hCursor = LoadCursor(NULL,IDC_ARROW);
wincl.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wincl.cbWndExtra = WINDOW_WND_EXTRA_BYTES;
return RegisterClassEx(&wincl);
}
SimpleWindow::SimpleWindow(Content__ *obj,const char *title, size_t w,size_t h, int style,int ex_style)
: Window( createWindow(obj,title,NULL, w,h, style,ex_style) ),
app_ctx(*this)
{
msg.message = 0;
show();
}
bool SimpleWindow::isOpen()
{
return msg.message != WM_QUIT;
}
void SimpleWindow::close()
{
DestroyWindow(*this);
}
const MSG& SimpleWindow::getMessage()
{
GetMessageA(&msg,*this,0,0);
return msg;
}
const MSG& SimpleWindow::peekMessage()
{
PeekMessageA(&msg,*this,0,0,PM_REMOVE);
return msg;
}
void SimpleWindow::dispatchMessage(const MSG &msg)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}}
main.cpp
#include <Jav/AutoObject.h>
#include <Jav/win32/window/SimpleWindow.h>
using namespace Jav::win32;
class Content : public Content__
{
IAutoComplete *pac = NULL;
IAutoComplete2 *pac2 = NULL;
//IUnknown *punkSource;
//ColumnList columnList;
public:
~Content()
{
if(pac) pac->Release();
if(pac2) pac2->Release();
}
void onCreate(HWND hwnd,CREATESTRUCTA*)override
{
throw; //doesn't throw or terminate
HWND textBox; // pretend this is an edit control
attachAutoCompleteObject(textBox); //doesn't throw either
}
void attachAutoCompleteObject(HWND hwnd)
{
HRESULT hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pac));
if(FAILED(hr)) throw "Failed to create AutoComplete Object\n";
hr = pac->Init(hwnd, &columnList, NULL, NULL);
if(FAILED(hr)) throw "Failed to attach auto complete object\n";
hr = pac->QueryInterface(IID_PPV_ARGS(&pac2)); rep(pac2);
if (FAILED(hr)) throw "Failed to set autocomplete options\n";
hr = pac2->SetOptions(ACO_AUTOSUGGEST);
}
};
int main()
{
Content content;
SimpleWindow win(&content,"",640,480);
while(win.isOpen())
{
auto &msg = win.getMessage();
win.dispatchMessage(msg);
}
}
【问题讨论】:
-
这甚至无法编译
-
你应该扔一个物体...
-
我的意思是终止程序。但是程序继续运行,就好像没有遇到任何抛出一样。我确实尝试了 throw object 版本。
标签: c++ exception visual-c++ throw