Process remains on app exit

After I close the main window of my app, process remains listed in windows task manager's processes list.

Here's the code below, anyone has an idea what to modify to successfully exit process on app exit (or main window close).

int WINAPI WinMain(HINSTANCE inst,HINSTANCE prev,LPSTR cmd,int show)
{
    HRESULT hr = CoInitialize(0); MSG msg={0}; DWORD no;

    IGraphBuilder*  graph= 0;  hr = CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&graph );
    IMediaControl*  ctrl = 0;  hr = graph->QueryInterface( IID_IMediaControl, (void **)&ctrl );

    ICreateDevEnum* devs = 0;  hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
    IEnumMoniker*   cams = 0;  hr = devs?devs->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &cams, 0):0;  
    IMoniker*       mon  = 0;  hr = cams->Next (1,&mon,0);  // get first found capture device (webcam?)    
    IBaseFilter*    cam  = 0;  hr = mon->BindToObject(0,0,IID_IBaseFilter, (void**)&cam);
                               hr = graph->AddFilter(cam, L"Capture Source"); // add web cam to graph as source
    IEnumPins*      pins = 0;  hr = cam?cam->EnumPins(&pins):0;   // we need output pin to autogenerate rest of the graph
    IPin*           pin  = 0;  hr = pins?pins->Next(1,&pin, 0):0; // via graph->Render
                               hr = graph->Render(pin); // graph builder now builds whole filter chain including MJPG decompression on some webcams
    IEnumFilters*   fil  = 0;  hr = graph->EnumFilters(&fil); // from all newly added filters
    IBaseFilter*    rnd  = 0;  hr = fil->Next(1,&rnd,0); // we find last one (renderer)
                               hr = rnd->EnumPins(&pins);  // because data we are intersted in are pumped to renderers input pin 
                               hr = pins->Next(1,&pin, 0); // via Receive member of IMemInputPin interface
    IMemInputPin*   mem  = 0;  hr = pin->QueryInterface(IID_IMemInputPin,(void**)&mem);

    DsHook(mem,6,Receive); // so we redirect it to our own proc to grab image data

    hr = ctrl->Run();   

    while ( GetMessage(   &msg, 0, 0, 0 ) ) {  
        TranslateMessage( &msg );   
        DispatchMessage(  &msg ); 
    }
};

Upvotes: 0

Views: 299

Answers (1)

Qaz
Qaz

Reputation: 61900

Disclaimer: I made no attempt to make this look pretty or do error checking. It works as far as I can tell (when I close the window, the application ends), but it's not exemplary code at all.

The window does not post a WM_QUIT message on its own; you have to do that yourself. You can do it as follows:

Create a window for messages:

WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = proc;        // function which will handle messages
wx.hInstance = GetModuleHandle(0);
wx.lpszClassName = "some class";
RegisterClassEx(&wx);
HWND hwnd = CreateWindowEx(0, "some class", "some name", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);

Make a IMediaEventEx * and use it to direct notifications to the window:

I assume a global IMediaEventEx *event;. Please don't do it the quick dirty way.

graph->QueryInterface(IID_IMediaEventEx, (void **) &event);
event->SetNotifyWindow((OAHWND) hwnd, WM_APP + 1, 0);

Make the window procedure handle the case of the user aborting:

LRESULT CALLBACK proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if (msg == WM_APP + 1) {
        long evt;
        LONG_PTR param1, param2;

        while (SUCCEEDED(event->GetEvent(&evt, &param1, &param2, 0))) {
            event->FreeEventParams(evt, param1, param2);

            if (evt == EC_USERABORT) {
                PostQuitMessage(0);
            }
        }
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

Upvotes: 1

Related Questions