MessageBox does not work in a catch of an exception - c++

Well I have 2 issues but my main concern right now is my catch exception. Here is the code...
int GXRenderManager::Ignite(HINSTANCE * hinst, int * nCmd, GXDEVICE DeviceType, int width, int height)
{
try
{
GXRenderManager::hinstance = hinst;
GXRenderManager::nCmdShow = nCmd;
GXRenderManager::height = height;
GXRenderManager::width = width;
InitWindows();
switch(DeviceType)
{
case DIRECTX:
GXRenderManager::renderDevice = new GXDX;
break;
case OPENGL:
GXRenderManager::renderDevice = new GXGL;
break;
default:
throw GXException(L"Error Finding Video Device");
}
Device()->StartUp(GXRenderManager::mainWindow ,width, height); //Error happens here
}
catch(GXVideoException &e)
{
MessageBox(0,e.pReason,L"GXVideoException",1);//Catch happens but no message box
return 0;
}
catch(GXWindowsException &e)
{
MessageBox(0,e.pReason,L"Windows Error",1);
return 0;
}
catch(GXException &e)
{
MessageBox(0,e.pReason,L"Error",1);
return 0;
}
return 1;
}
Here is where the error happens
void GXDX::StartUp(HWND* mainWindow,int w, int h)
{
width = w;
height = h;
this->mainWindow = mainWindow;
ID3D10Texture2D *backBufferSurface;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
swapChainDesc.BufferCount = 2;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.OutputWindow = *mainWindow;
swapChainDesc.Windowed = TRUE;
D3D10_DRIVER_TYPE driverType = D3D10_DRIVER_TYPE_HARDWARE;
HRESULT hr = D3D10CreateDeviceAndSwapChain(NULL,driverType,NULL,0,
D3D10_SDK_VERSION, &swapChainDesc,&swapChain,&dxDevice);
if(FAILED(hr))
throw GXVideoException(L"Problems retrieving directX device");
}
When I do a walk through. the D3D10CreateDeviceAndSwapChain returns a failure, therefore triggering the GXVideoException error.
It then catches and returns back to GXRenderManager class as shown below.
catch(GXVideoException &e)
{
MessageBox(0,e.pReason,L"GXVideoException",1);
return 0;
}
At this point in time, If I put my cursor over the &e, I clearly see my message "Problems retrieving directX device". But the message box does not show
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
if(GXRenderManager::Ignite(&hInstance, &nCmdShow,DIRECTX) != 1)
return 0;
//NEVER REACHES THE RUN METHOD BELOW YET THE MAIN WINDOW REMAINS OPEN
GXRenderManager::Run();
return 0;
}
Another thing I find strange is that my created window remains showing but never reaches the main loop. It is like the application is idle due to the message box, but the message box is not showing...
I also would like to add that the static member renderDevice is a interface datatype. GXDX is of course a implemented class of the interface.
GXDX class includes the GXException Header so it is able to throw those exceptions so the main GXRenderManager can catch them.
[EDIT]
Another thing I would like to add is if I remove the Show window method
ShowWindow(*GXRenderManager::mainWindow, *GXRenderManager::nCmdShow);
It works. So as long as my main application window is not open. My message box appears like its suppose to.
[EDIT]
Prior to dauphic response which fixed part of the problem, I went on and edited my code. My catch now looks like this
catch(GXVideoException &e)
{
MessageBox(*GXRenderManager::mainWindow,e.pReason,L"GXVideoException",1);
return 0;
}
But now my application opens and then immediately closes without displaying the box. mainWindow is a pointer to my base window. So I had to dereference the pointer.
[EDIT]
The windows pointer is bad

If a dialog is present, MessageBox should always be passed a handle to it, rather than 0. Only pass MessageBox 0 if no dialog is available.
Side note, I don't understand the exact reason for this, so it would be great if someone else could give insight.
It's also possible that your message box is being attached to your dialog, and because your dialog isn't active, the message box isn't showing. Pressing alt when it hangs may cause it to show.

Related

Detecting CTRL+Wheel with CHtmlView

I know how to set the zoom factor for a CHtmlView:
HRESULT CChristianLifeMinistryHtmlView::SetZoomFactor(long iZoom, bool bRefreshBrowser /*true*/)
{
HRESULT hr = S_OK;
VARIANT vZoom;
m_lZoomFactor = iZoom;
if (bRefreshBrowser)
{
vZoom.vt = VT_I4;
vZoom.lVal = iZoom;
hr = ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &vZoom, nullptr);
}
return hr;
}
HRESULT CChristianLifeMinistryHtmlView::ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
{
HRESULT hr;
ASSERT(m_pBrowserApp != NULL);
hr = m_pBrowserApp->ExecWB(cmdID, cmdexecopt, pvaIn, pvaOut);
return hr;
}
I have just introduced a CStatusBar into the main editor that encompasses this view and one of my users has stated that they use CTRL + Wheel to change the zoom factor.
I have my menu structure with associated hotkeys that the user can use to change the zoom, thus my status bar pane is updated to the right value they selected.
But when they use the CTRL + Wheel to change the zoom my application is not detecting this. So they zoom in or out to a scale and my status bar pane is staying at the original zoom factor.
With MFC and the CHtmlView web browser control how to I detect when they have changed the zoom using CTRL + Wheel so I can update my status pane?
If this is CHtmlView with Doc/View structure, use PreTranslateMessage to catch messages.
Documentation for WM_MOUSEWHEEL suggests several macros for finding the state of virtual keys and wheel movement:
BOOL CMyHtmlView::PreTranslateMessage(MSG* pmsg)
{
if(pmsg->message == WM_MOUSEWHEEL)
{
int fwKeys = GET_KEYSTATE_WPARAM(pmsg->wParam);
int zDelta = GET_WHEEL_DELTA_WPARAM(pmsg->wParam);
if (fwKeys & MK_CONTROL)
{
//mousewheel + control key is down
TRACE("%d %d\n", zDelta, zDelta / WHEEL_DELTA);
//update statusbar, or return TRUE to handle this manually
}
}
return CHtmlView::PreTranslateMessage(pmsg);
}
CHtmlView also has its own CHtmlView::ExecWB method to set and get the zoom value etc.
CHtmlView::OnUpdateUI should also send notification for the change.
But the browser may not send a signal at the right time. Just make a timer to wait 1 second after detecting CTRL+WHEEL. Example:
BEGIN_MESSAGE_MAP(CMyHtmlView, CHtmlView)
ON_WM_TIMER()
END_MESSAGE_MAP()
const int ID_TIMER_ZOOM = 1;
BOOL CMyHtmlView::PreTranslateMessage(MSG* pmsg)
{
if(pmsg->message == WM_MOUSEWHEEL)
if (GET_KEYSTATE_WPARAM(pmsg->wParam) & MK_CONTROL)
SetTimer(ID_TIMER_ZOOM, 1000, NULL); //start timer for detecting zoom
return CHtmlView::PreTranslateMessage(pmsg);
}
void CMyHtmlView::OnTimer(UINT_PTR timer_id)
{
if(timer_id == ID_TIMER_ZOOM)
{
//get the zoom value
VARIANT vZoom;
vZoom.vt = VT_I4;
vZoom.lVal = 0;
ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, nullptr, &vZoom);
TRACE("zoom %d\n", vZoom.lVal);
//kill the timer
KillTimer(timer_id);
}
}

How to block resizing after a double-click on a dialog window's top or bottom edges in Windows 10?

I'm coding a customized popup window with C++ using Win32. The condition for this popup window is that it can be only resized from the bottom down. The following is the implementation of such restriction:
RECT rcInitialWindowRectangle = {0};
//The dialog has WS_THICKFRAME style
LRESULT CALLBACK DlgWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
case WM_INITDIALOG:
{
//Set minimum window size
::GetWindowRect(hDlg, &rcInitialWindowRectangle);
}
break;
case WM_SIZING:
{
//Restrict sizing on all sides but bottom
if(wParam != WMSZ_BOTTOM)
{
RECT* pRcWnd = (RECT*)lParam;
//Preserve all sides but bottom
int b = pRcWnd->bottom;
*pRcWnd = rcInitialWindowRectangle;
pRcWnd->bottom = b;
return TRUE;
}
}
break;
case WM_GETMINMAXINFO:
{
//The following is needed to restrict minimum window size
int w = rcInitialWindowRectangle.right - rcInitialWindowRectangle.left;
if(w != 0)
{
MINMAXINFO* pMMI = (MINMAXINFO*)lParam;
pMMI->ptMinTrackSize.x = w;
pMMI->ptMinTrackSize.y = rcInitialWindowRectangle.bottom - rcInitialWindowRectangle.top;
pMMI->ptMaxTrackSize.x = w;
}
}
break;
case WM_NCHITTEST:
{
//The following is needed to display correct cursor for resizing
POINT pnt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
RECT rcWnd;
::GetWindowRect(hDlg, &rcWnd);
//L, T, R, B
RECT rcBtm = {rcInitialWindowRectangle.left,
rcWnd.bottom - 16, //Some arbitrary border
rcInitialWindowRectangle.right,
rcWnd.bottom};
return ::PtInRect(&rcBtm, pnt) ? HTNOWHERE : HTBORDER;
}
break;
return 0;
}
So this works except one thing. On Windows 10, there's evidently a new feature -- when someone double-clicks on the bottom (or top) edge of a window -- here's an example with Notepad so that you can try:
that window is resized (stretched) to the top and bottom of the screen (akin to maximization, but only vertically.)
So my question is how do I block this double-click resizing? (In my case the top of the popup window should not move.)
PS. My first instinct was to block all double-clicks on the window's edge, but then I thought that maybe there's a less barbaric way to achieve this?
You are already handling WM_NCHITTEST. Handle WM_NCLBUTTONDBLCLK and don't forward to DefWindowProc unless the hit test (in wParam) indicates the lower frame.
here's the workaround that seems to work for me. It is not really about blocking the double-clicks. (Apart from subclassing the WndProc of a dialog box, which I haven't tried, I failed to block that double-click effect in DlgProc alone.) My workaround presented below is to achor the top of the popup window and let it drop down to the bottom of the screen, if the user who double-clicks the bottom border wants similar stuff to happen.
Since this does not answer my original question, I won't mark it as such.
//Add this case statement to my original code
case WM_WINDOWPOSCHANGING:
{
WINDOWPOS* pWP = (WINDOWPOS*)lParam;
if(!(pWP->flags & (SWP_NOMOVE | SWP_NOSIZE)))
{
int w = rcInitialWindowRectangle.right - rcInitialWindowRectangle.left;
if(w > 0)
{
//Anchor the top of the popup window
pWP->x = rcInitialWindowRectangle.left;
pWP->y = rcInitialWindowRectangle.top;
pWP->cx = w;
int h = pWP->cy;
//Make sure that the height fits the screen
POINT pnt = {pWP->x, pWP->y};
MONITORINFO mi = {0};
mi.cbSize = sizeof(mi);
if(::GetMonitorInfo(::MonitorFromPoint(pnt, MONITOR_DEFAULTTONEAREST), &mi))
{
if(pWP->y + h > mi.rcWork.bottom)
{
int nMinDefaultH = rcInitialWindowRectangle.bottom -
rcInitialWindowRectangle.top;
int nAh = mi.rcWork.bottom - y;
if(nAh >= nMinDefaultH)
h = nAh;
else
h = nMinDefaultH;
}
}
pWP->cy = h;
}
}
}
break;

Weird array behavior in classes along with Windows DCs (C++)?

I'm working on creating a text based Windows game, and I am having a problem (I guess) with arrays not working the same within a class scope as within the main function. As far as I can tell it is some kind of interaction between a larger array class member (or large total amount of variables) and Windows creating a DC or other Windows API calls and/or variables.
What I want to do is a have a class called Map that contains a two dimensional array of Tiles. Tile is just a simple struct with basic tile information. I would like to make the array 256 x 256. This shouldn't be a problem as far as I can figure. Each Tile should be 32 bytes. That's 2 MB total for the array.
However, the game crashes when I declare a variable of the Map class in the main function, and then do things with Windows DCs. The return value seems to vary, In the current form, it usually returns 255, but I have also gotten "process terminated with status -1073741571". A 128 x 128 array does work in the class though. It also works fine if I remove either the array or the code in DisplayScreen. And as I implied, it also works if I just move the array of Tiles to the main function.
I'm honestly baffled. I have no idea what the difference would be. Nothing is going out of scope. Doesn't matter if it is a public or private member. Non dynamic class members should all get declared on the stack and it shouldn't work any differently in a class versus otherwise, right?
For other information, I am using Code::Blocks with the Min GW compiler. Everything is up to date. I am running Windows 10. My computer specs shouldn't be an issue either, but if it matters, I have 16 GB memory and a 4Ghz Athlon FX 8 core processor.
Edit: Here is the full code, so nothing is left out
Game.h:
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
struct Tile
{
char chr[2];
int r[2], b[2], g[2];
bool solid;
bool translucent;
int opacity;
};
class Map
{
Tile tileMap[256][256];
public:
Map();
};
Map::Map()
{
int i, j;
for(i=0;i<256;i++)
{
for(j=0;j<256;j++)
{
tileMap[i][j].chr[0] = 'X';
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
tileMap[i][j].chr[1] = ' ';
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
main.cpp:
#include <windows.h>
#include "Game.h"
#define FRAMERATE 60
//Function declarations
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
void DisplayScreen(HWND pWnd, Map &pMap);
//Make the class name into a global variable
char strClassName[ ] = "GameApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpstrArgument,
int nCmdShow)
{
HWND hWnd; //This is the handle for our window
MSG messages; //Here messages to the application are saved
WNDCLASSEX wndClassEx; //Data structure for the windowclass
Map test;
DWORD sysTimer;
DWORD sysPrevTime = 0;
DWORD timerDelta = 1000 / FRAMERATE;
//Get a handle for the whole screen
HDC hDC = GetDC(NULL);
//Initalize the Window structure
wndClassEx.hInstance = hThisInstance;
wndClassEx.lpszClassName = strClassName;
wndClassEx.lpfnWndProc = WindowProcedure;
wndClassEx.style = CS_DBLCLKS;
wndClassEx.cbSize = sizeof (WNDCLASSEX);
wndClassEx.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hCursor = LoadCursor (NULL, IDC_ARROW);
wndClassEx.lpszMenuName = NULL; //No menu
wndClassEx.cbClsExtra = 0;
wndClassEx.cbWndExtra = 0;
wndClassEx.hbrBackground = CreateSolidBrush(RGB(0,0,0));
//Register the window class, and if it fails quit the program
if (!RegisterClassEx (&wndClassEx))
return 0;
//Create Window with registered window class
hWnd = CreateWindowEx (
0,
strClassName, //Class name
"Game Test", //Title Text
WS_OVERLAPPEDWINDOW, //default window type
0, //X pos of window at top left
0, //Y pos of window at top left
GetDeviceCaps(hDC, HORZRES), //Set window width to screen width
GetDeviceCaps(hDC, VERTRES), //Set window height to screen height
HWND_DESKTOP, //Child-window to desktop
NULL, //No menu
hThisInstance, //Program Instance handler
NULL); //No Window Creation data
//Removes borders from the window
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP);
//Make the window visible on the screen
ShowWindow (hWnd, nCmdShow);
//Run the message and game loop
while (true)
{
while(PeekMessage(&messages,NULL,0,0, PM_REMOVE))
{
if (messages.message == WM_QUIT)
{
ReleaseDC(NULL, hDC);
DestroyWindow(hWnd);
return 0;
}
TranslateMessage(&messages);
DispatchMessage(&messages);
}
sysTimer = timeGetTime();
if (sysTimer >= (sysPrevTime + timerDelta) )
{
sysPrevTime = sysTimer;
DisplayScreen(hWnd, test);
}
}
}
//This function is called by the Windows function DispatchMessage()
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage (0); //Send WM_QUIT to the message queue
break;
default:
return DefWindowProc (hWnd, message, wParam, lParam);
}
return 0;
}
void DisplayScreen(HWND pWnd, Map &pMap)
{
HDC hDC = GetWindowDC(pWnd);
HDC hdcBuf = CreateCompatibleDC(hDC);
HBITMAP hbmBuf = CreateCompatibleBitmap(hDC, 800, 600);
HFONT hMapFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
HFONT hTxtFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
SelectObject(hdcBuf, hbmBuf);
SelectObject(hdcBuf, hMapFont);
SetBkColor(hdcBuf, RGB(0,0,0));
SetTextColor(hdcBuf, RGB(255,255,255));
//Draw to the buffer
TextOut(hdcBuf, 10, 10, "Hello World #", 15);
//Tranfers the buffer to the Screen
BitBlt(hDC, 100, 100, 800, 600, hdcBuf, 0, 0, SRCCOPY);
//Release all object handles
DeleteObject(hTxtFont);
DeleteObject(hMapFont);
DeleteObject(hbmBuf);
DeleteDC(hdcBuf);
ReleaseDC(pWnd, hDC);
}
It crashes with even one instance of something creating a DC. It works fine otherwise creating and destroying the DCs and displaying the bitmap over and over again even if I leave it for an hour. Once I create that class with the large array in it though, it just dies.
I actually used to have the Display function as a class function and I moved it out because I thought that was the problem, but it wasn't.
Interestingly, if I change the declaration from 'Map test;' to 'Map* test = new Map;' and change the rest of the program appropriately, it works. Honestly though, doing that just seems kind of dumb, and I think that would slow everything down if I don't have a good reason to put everything on the heap. Plus, I don't like bandages. If there is a problem I'd rather fix it.
Any ideas?
You have a stack overflow (the condition, not the website).
The problem can be reproduced in this program:
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
Map test;
return 0;
}
It fails because it reaches stack limit.
Also tileMap[i][j].chr[2] is out of bound. It is declared as char chr[2]; valid index is 0 and 1. It can only go up to tileMap[i][j].chr[1]
Ditto b[], r[], and g[]
Change the Map class so that it allocates memory on heap and fix chr:
class Map
{
//Tile tileMap[256][256];
Tile **tileMap;
public:
Map();
~Map();
};
Map::Map()
{
int i, j;
tileMap = new Tile*[256];
for (i = 0; i < 256; i++)
tileMap[i] = new Tile[256];
for (i = 0; i<256; i++)
{
for (j = 0; j<256; j++)
{
//tileMap[i][j].chr[1] = 'X';
tileMap[i][j].chr[0] = 'X'; //<== meant to be 0?
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
//tileMap[i][j].chr[2] = ' ';
tileMap[i][j].chr[1] = ' '; //<== meant to be 1?
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
Map::~Map()
{
int i = 0;
for (i = 0; i < 256; i++)
delete[]tileMap[i];
delete[]tileMap;
}

GetTextExtentPoint32(m_hAttribDC, lpszString, nCount, &size))

My program is to display some points with their positions(x,y) on a graph. When I use mouse to drag any point, its position will automatically changed. Updated position is implemented following this code(using thread):
m_thread =AfxBeginThread((AFX_THREADPROC)MainThread,this)
UINT CAtwWnd::MainThread(LPVOID pParam)
{
CAtwWnd *pMainDlg = (CAtwWnd*)pParam;
static SChartXYPoint pPoint;
TCHAR strTemp[32]={0,};
while(1)
{
pMainDlg->m_chart.EnableRefresh(false);
pMainDlg->InitGraph1();
wsprintf(strTemp, _T("[%d](%d,%d)"), (int)index,(int)xPoint,(int) yPoint);
pBalloon[index]->SetLabelText(strTemp);
pBalloon[index] = pMainDlg->m_pPointSeries->CreateBalloonLabel(index, strTemp);
pBalloon[index]->SetVisisble(true);
pMainDlg->m_pPointSeries->SetVisible(true);
pMainDlg->m_chart.EnableRefresh(true);
pMainDlg->SetAtwGraphStep(1);
}
return 0;
}
Mean while:
void CChartLabel<PointType>::SetLabelText(const TChartString& strText)
{
m_strLabelText = strText;
m_pParentCtrl->RefreshCtrlAtw();
}
And:
void CChartCtrl::RefreshCtrlAtw()
{
// Window is not created yet, so skip the refresh.
if (!GetSafeHwnd())
return;
if (m_iEnableRefresh < 1)
{
m_bPendingRefresh = true;
return;
}
// Retrieve the client rect and initialize the
// plotting rect
CClientDC dc(this) ;
CRect ClientRect;
GetClientRect(&ClientRect);
m_PlottingRect = ClientRect;
// If the backgroundDC was not created yet, create it (it
// is used to avoid flickering).
if (!m_BackgroundDC.GetSafeHdc() )
{
CBitmap memBitmap;
m_BackgroundDC.CreateCompatibleDC(&dc) ;
memBitmap.CreateCompatibleBitmap(&dc, ClientRect.Width(),ClientRect.Height()) ;
m_BackgroundDC.SelectObject(&memBitmap) ;
}
// Draw the chart background, which is not part of
// the DrawChart function (to avoid a background when
// printing).
DrawBackground(&m_BackgroundDC, ClientRect);
ClientRect.DeflateRect(3,3);
DrawChart(&m_BackgroundDC,ClientRect);
for (int i=0; i<4 ;i++)
{
if (m_pAxes[i])
m_pAxes[i]->UpdateScrollBarPos();
}
Invalidate();
}
when dragging points on graph I gets these errors somtimes: Debug Assertion Failed ( afxwin1.inl, line 639, and 646)
_AFXWIN_INLINE CSize CDC::GetTextExtent(LPCTSTR lpszString, int nCount) const
{
ASSERT(m_hAttribDC != NULL);
SIZE size;
VERIFY(::GetTextExtentPoint32(m_hAttribDC, lpszString, nCount, &size));
return size;
}
_AFXWIN_INLINE CSize CDC::GetTextExtent(const CString& str) const
{
ASSERT(m_hAttribDC != NULL);
SIZE size;
VERIFY(::GetTextExtentPoint32(m_hAttribDC, str, (int)str.GetLength(), &size));
return size;
}
Could you help me to fix this problem? I tried to find some ways to fix but doesn't work. :(
My answer is just a guess, but the reason might be caused by using MFC objects from one thread (the creator) in a second thread. And it is a guess because you didn't told us what the ASSERT say and what VS version you are using.
The problem: When you create some objects in the MFC, the handle values are saved in a map that allows the MFC to find the object only with the handle value.
This handle maps are stored per thread.
Also if a window object stores other objects that are associated with those handle maps, the usage from another thread will fail.
So the answer can be found in the call stack. It tells you who uses such an object. And the object that causes the problem is simply identified by the ASSERT.

How to implement code for multiple buttons using c++ in Silverlight for Windows Embedded

I have referred the following link:
Silverlight for Windows Embedded
By referring this link i created a demo application which consist of two buttons created using Microsoft expression blend 2 tools. And then written a code referring the above site. Now my button names are "Browser Button" and "Media Button". On click of any one of the button i should able to launch the respective application. I was able to do for "Browser Button" but not for "Media Button" and if i do for "Media Button" then i am not able to do for "Browser Button".. I mean to say that how should i create event handler for both the buttons.
This is the code in c++ which i should modify
class BtnEventHandler
{
public:
HRESULT OnClick(IXRDependencyObject* source,XRMouseButtonEventArgs* args)
{
RETAILMSG(1,(L"Browser event"));
Execute(L"\\Windows\\iesample.exe",L"");
return S_OK;
}
};
// entry point for the application.
INT WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,int nCmdShow)
{
PrintMessage();
int exitCode = -1;
HRESULT hr = S_OK;
if (!XamlRuntimeInitialize())
return -1;
HRESULT retcode;
IXRApplicationPtr app;
if (FAILED(retcode=GetXRApplicationInstance(&app)))
return -1;
if (FAILED(retcode=app->AddResourceModule(hInstance)))
return -1;
XRWindowCreateParams wp;
ZeroMemory(&wp, sizeof(XRWindowCreateParams));
wp.Style = WS_OVERLAPPED;
wp.pTitle = L"Bounce Test";
wp.Left = 0;
wp.Top = 0;
XRXamlSource xamlsrc;
xamlsrc.SetResource(hInstance,TEXT("XAML"),MAKEINTRESOURCE(IDR_XAML1));
IXRVisualHostPtr vhost;
if (FAILED(retcode=app->CreateHostFromXaml(&xamlsrc, &wp, &vhost)))
return -1;
IXRFrameworkElementPtr root;
if (FAILED(retcode=vhost->GetRootElement(&root)))
return -1;
IXRButtonBasePtr btn;
if (FAILED(retcode=root->FindName(TEXT("BrowserButton"), &btn)))
return -1;
IXRDelegate<XRMouseButtonEventArgs>* clickdelegate;
BtnEventHandler handler;
if(FAILED(retcode=CreateDelegate
(&handler,&BtnEventHandler::OnClick,&clickdelegate)))
return -1;
if (FAILED(retcode=btn->AddClickEventHandler(clickdelegate)))
return -1;
UINT exitcode;
if (FAILED(retcode=vhost->StartDialog(&exitcode)))
return -1;
return exitCode;
}
I have to add event handler for both the button so that on emulator whenever i click on any one of the button i should be able to launch the respective applications.
Thanks in advance
You can create two seperate functions to be the handlers for each button.
If you want the same handler to identify which button was pressed and act accordingly you can read the following MSDN article that demonstrates that.
I have not tried this, but you can also use IXRDependencyObject::GetName of the source object to know which button was pressed.
Your handler would look like:
HRESULT OnClick(IXRDependencyObject* source,XRMouseButtonEventArgs* args)
{
BSTR pName[50];
source->GetName(pName);
if (_tcscmp(L"BrowserEvent", LPCWSTR(pName)) == 0)
{
RETAILMSG(1,(L"Browser event"));
Execute(L"\\Windows\\iesample.exe",L"");
}
else if (_tcscmp(L"BrowserEvent", LPCWSTR(pName)) == 0)
{
/* Handle another button or element */
}
return S_OK;
}