wglCreateContext fails with error code 6 (Invalid Handle) - windows

I'm trying to create a wgl context according to the tutorial at https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context_(WGL). For whatever reason, wglCreateContext returns null, and GetLastError returns 6, or Invalid Handle. I have used the tutorial before, and it worked just fine.
I'm trying to create a dummy context to a hidden window so that I can create another context for the user window. What's going on?
The Windows API is referred through the winAPI identifier, and wgl is a global struct containing function pointers to OpenGL.
struct WglContext
{
winAPI.HDC hdc;
winAPI.HGLRC handle;
}
__gshared Win32GL wgl;
///WGL-specific global data.
struct Win32GL
{
import oswald : OsWindow, WindowConfig, WindowError;
OsWindow helperWindow;
winAPI.HINSTANCE instance;
PFN_wglCreateContext createContext;
PFN_wglDeleteContext deleteContext;
PFN_wglGetProcAddress getProcAddress;
PFN_wglMakeCurrent makeCurrent;
PFN_wglCreateContextAttribsARB createContextAttribsARB;
PFN_wglGetExtensionStringARB getExtensionStringARB;
PFN_wglGetExtensionStringEXT getExtensionStringEXT;
bool extensionsAreLoaded;
static void initialize()
{
if (wgl.instance !is null)
return; //The library has already been initialized
WindowConfig cfg;
cfg.title = "viewport_gl_helper";
cfg.hidden = true;
auto windowError = OsWindow.createNew(cfg, &wgl.helperWindow);
if (windowError != WindowError.NoError)
{
import std.conv : to;
assert(false, "Failed to create helper window: " ~ windowError.to!string);
}
wgl.instance = winAPI.LoadLibrary("opengl32.dll");
if (wgl.instance is null)
assert(false, "Viweport failed to load opengl32.dll");
wgl.bind(cast(void**)&wgl.createContext, "wglCreateContext\0");
wgl.bind(cast(void**)&wgl.deleteContext, "wglDeleteContext\0");
wgl.bind(cast(void**)&wgl.getProcAddress, "wglGetProcAddress\0");
wgl.bind(cast(void**)&wgl.makeCurrent, "wglMakeCurrent\0");
}
static void terminate()
{
if (!wgl.instance)
return;
winAPI.FreeLibrary(wgl.instance);
wgl.helperWindow.destroy();
}
void bind(void** func, in string name)
{
*func = winAPI.GetProcAddress(this.instance, name.ptr);
}
}
struct WglContext
{
winAPI.HDC hdc;
winAPI.HGLRC handle;
}
WglContext wglCreateTmpContext()
{
assert(wgl.instance);
winAPI.PIXELFORMATDESCRIPTOR pfd;
pfd.nSize = winAPI.PIXELFORMATDESCRIPTOR.sizeof;
pfd.nVersion = 1;
pfd.dwFlags = winAPI.PFD_DRAW_TO_WINDOW | winAPI.PFD_SUPPORT_OPENGL | winAPI.PFD_DOUBLEBUFFER;
pfd.iPixelType = winAPI.PFD_TYPE_RGBA;
pfd.cColorBits = 24;
auto hdc = winAPI.GetDC(wgl.helperWindow.platformData.handle);
const pixelFormat = winAPI.ChoosePixelFormat(hdc, &pfd);
if (winAPI.SetPixelFormat(hdc, pixelFormat, &pfd) == winAPI.FALSE)
assert(false, "Failed to set pixel format for temp context");
writeln(hdc);
writeln(pixelFormat);
winAPI.HGLRC context = wgl.createContext(hdc);
if (context is null)
{
import std.conv: to;
assert(false, "Failed to create temp context: Error Code " ~ winAPI.GetLastError().to!string);
}
if (wgl.makeCurrent(hdc, context) == winAPI.FALSE)
{
wgl.deleteContext(context);
assert(false, "Failed to make temp context current");
}
return WglContext(hdc, context);
}
void main()
{
wgl.initialize(); //Fetches function pointers, and loads opengl32.dll
auto context = wglCreateTmpContext();
wglDeleteContext(context); //Delegates to wgl.deleteContext
wgl.terminate(); //Unloads opengl32.dll and nulls function pointers
}

I know nothing on that winAPI you use. Anyhow, I'm sure of:
You must:
Create a window and get its HWND handle (Windows definition of
HWND, see below). Tipically the window uses WS_CLIPCHILDREN | WS_CLIPSIBLINGS
style; but try also the WS_OVERLAPPEDWINDOW as in the link you
posted.
Verify you get a valid HWND, and a valid HDC from it.
HWND and HDC are defined as *void. I would not trust on auto.

Related

I want to copy, paste and cut content in my CEdit from my Clipboard

This is the event handlers i implemented to the copy, paste and Cut buttons in my MFCRibbonBar:
in the MyRibbonView.cpp:
void CMyRibbonView::OnEditCopy()
{
CWnd *wnd = GetFocus();
if (wnd == pEdit)
pEdit->Copy();
if (!OpenClipboard())
{
AfxMessageBox(_T("Cannot open the Clipboard"));
return;
}
if (!EmptyClipboard())
{
AfxMessageBox(_T("Cannot empty the Clipboard"));
return;
}
HGLOBAL hGlob = GlobalAlloc(GMEM_FIXED, 64);
strcpy_s((char*)hGlob, 64, "Current selection\r\n");
if (::SetClipboardData(CF_TEXT, hGlob) == NULL)
{
CString msg;
msg.Format(_T("Unable to set Clipboard data, error: %d"), GetLastError());
AfxMessageBox(msg);
CloseClipboard();
GlobalFree(hGlob);
return;
}
CloseClipboard();
}
void CMyRibbonView::OnEditPaste()
{
if (OpenClipboard())
{
HANDLE hClipboardData = GetClipboardData(CF_TEXT);
char *pchData = (char*)GlobalLock(hClipboardData);
CString strFromClipboard;
strFromClipboard = pchData;
pEdit->SetWindowText(strFromClipboard);
GlobalUnlock(hClipboardData);
CloseClipboard();
}
}
void CMyRibbonView::OnEditCut()
{
OnEditCopy();
pEdit->SetWindowText(L" ");
}
There is no errors, it's just not working. I tested it by adding the messages to check if it's actually the data or not but they're not popping up.
You need to GlobalLock your hGlob memory before copying your character string into it (this operation converts it into a usable pointer for your process - see here), and then call GlobalUnlock after you've done that (so that the clipboard can access hGlob):
HGLOBAL hGlob = GlobalAlloc(GMEM_FIXED, 64); // Maybe also need GMEM_MOVEABLE here instead?
char* cCopy = (char*)GlobalLock(hGlob);
strcpy_s(cGlob, 64, "Current selection\r\n");
GlobalUnlock(hGlob);
if (::SetClipboardData(CF_TEXT, hGlob) == NULL)
{
//...
And you'll need a similar arrangement for the paste operation.

firebreath plugin create a full screen window, but the window always under the browser window when it appers, how can I bring it to top

CaptureScreenApp app;
int MyPluginAPI::captureScreen(const FB::JSObjectPtr& callback)
{
boost::thread cs(boost::bind(&CaptureScreenApp ::captureScreen,
app, callback));
return 1;
}
class CaptureScreenApp {
public:
CaptureScreenApp() {
HRESULT hRes;
hRes = OleInitialize(NULL);
ATLASSERT(SUCCEEDED(hRes));
AtlInitCommonControls(ICC_WIN95_CLASSES);
g_Module.Init(NULL, NULL);
};
~CaptureScreenApp() {
g_Module.Term();
OleUninitialize();
};
bool captureScreen() {
CMessageLoop theLoop;
CMainDialog g_MainDlg;
g_Module.AddMessageLoop(&theLoop);
if (NULL == g_MainDlg.Create(NULL)){
DWORD ret = GetLastError();
return FALSE;
}
g_MainDlg.ShowWindow(SW_SHOW);
g_MainDlg.UpdateWindow();
int nRet = theLoop.Run();
g_Module.RemoveMessageLoop();
return TRUE;
};
};
class CMainDialog : public CDialogImpl<CMainDialog>
{
public:
enum {IDD = IDD_MAIN};
....
}
the window(the new window is a full screen window with a desktop pic as the background) I create in CaptureScreenApp::captureScreen always under the browser window when it appears(browser window always actived in other word), what ever how I set the HWND_TOPMOST for the new window. like this:
enter link description here
how can i bring the full screen window to top when it appers?
SetWindowPos API lets you change Z order (make sure to read Remarks there). You create your window with NULL parent, so your window is completely independent from browser window, so there is nothing to push it to the front: it would be either you or interactive user.

how to host html control in my window using a buffer which contents a html file

I am developing a visual c++ applicatio(x64). what actually i am trying to do is that suppose we have a html file in window explorer(i mean file with file extension ".html"). when we single click on it we get its preview on preview pane(so we don't need to open this file we can see the file in preview pane on a single click to a file).
I have developed a similar type of application but in my case when i click on the "html file" i just get the code of that html file in preview pane(the code which you can see if you open that html file in notepad). which is not expected to happen but I want to have the preview of that "html file" not the code of that html file.
I think i need to host some browser control which will transform my html code in preview pane to the display of html file(If i am correct ???) How to do that ??
Here is my code for that-
IHTMLDocument2 * pDoc=NULL;
HRESULT hr2 = CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, (LPVOID *) &pDoc);
if (pDoc)
{
IPersistStreamInit *pPersist = NULL;
pDoc->QueryInterface(IID_IPersistStreamInit,(LPVOID *) &pPersist);
if (pPersist)
{
IMarkupServices *pMS = NULL;
pPersist->InitNew();
pPersist->Release();
pDoc->QueryInterface(IID_IMarkupServices,(LPVOID *) &pMS);
if (pMS)
{
IMarkupContainer *pMC = NULL;
IMarkupPointer *pMkStart = NULL;
IMarkupPointer *pMkFinish = NULL;
pMS->CreateMarkupPointer(&pMkStart);
pMS->CreateMarkupPointer(&pMkFinish);
pMS->ParseString(HtmlFileContents,0,&pMC,pMkStart,pMkFinish);
//this HtmlFileContents is actually a buffer of olechar type which contains the code of html file (the code which you see when you open the html file in notepad)
if (pMC)
{
IHTMLDocument2 *pNewDoc = NULL;
pMC->QueryInterface(IID_IHTMLDocument,(LPVOID *) &pNewDoc);
if (pNewDoc)
{
IHTMLElement *pBody;
pNewDoc->get_body(&pBody);
if (pBody)
{
BSTR strText;
pBody->get_innerText(&strText);
hr = instance->CreatePreviewWindowForHtml(strText); // this function is responsible for displaying the html file in window. you can see its definition below after this code.
SysFreeString(strText);
pBody->Release();
}
pNewDoc->Release();
}
pMC->Release();
}
if (pMkStart)
pMkStart->Release();
if (pMkFinish)
pMkFinish->Release();
pMS->Release();
pMS->Release();
}
}
pDoc->Release();
}
return true;
and the function defintion of CreatePreviewWindowForHtml() is as below-
CreatePreviewWindowForHtml(PCWSTR pszRtfWide)
{
assert(m_hwndPreview3 == NULL);
HRESULT hr = E_FAIL;
if (m_hwndPreview3 == NULL)
{
HRESULT hr5 = HRESULT_FROM_WIN32(GetLastError());
}
if (m_hinstEditLibrary == NULL)
{
// MSFTEDIT_CLASS used below comes from this binary
m_hinstEditLibrary = LoadLibraryW(L"msftedit.dll");
}
if (m_hinstEditLibrary == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
// Create the preview window
HWND pr = m_hwndPreview3 = CreateWindowExW(0, MSFTEDIT_CLASS, NULL,
WS_CHILD | WS_VSCROLL | WS_VISIBLE | ES_MULTILINE | ES_READONLY, // Always create read-only
m_rcParent.left, m_rcParent.top, RECTWIDTH(m_rcParent), RECTHEIGHT(m_rcParent),
m_hwndPreview, NULL, NULL,NULL);
if (m_hwndPreview3 == NULL)
{
MessageBoxA(m_hwndPreview3,strerror(hr),"BTN WND2", MB_ICONINFORMATION);
}
else
{
int const cchRtf = 1 + wcslen(pszRtfWide);
PSTR pszRtf = (PSTR)CoTaskMemAlloc(cchRtf);
if (pszRtf)
{
WideCharToMultiByte(CP_ACP, 0, pszRtfWide, cchRtf, pszRtf, cchRtf, NULL, NULL);
SETTEXTEX st = { ST_DEFAULT, CP_ACP };
LRESULT hr4=SendMessage(m_hwndPreview3, EM_SETTEXTEX, (WPARAM) &st, (LPARAM) pszRtfWide);
if (SUCCEEDED(hr4))
{
hr = AdjustDialogPositionAndSize();
SendMessage(m_hwndPreview3, EM_SETTEXTEX, (WPARAM) &st, (LPARAM) pszRtfWide);
}
CoTaskMemFree(pszRtf);
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
return hr;
}
Any ideas why i have the html code in my window ?? What to do in the code in order to get the preview of html file in my window rather then html code ??
Please tell me if any doubts in understanding me ??
You have the html code in your window because you choose a richedit as the text renderer and your text did not start with "{\rtf".
If you want html display, you need an html renderer instead of a rich edit, something like MFC's CHtmlEditCtrl. If you don't want to use MFC you can write an ActiveX container to host the webbrowser control directly.

Wrong PIDL got from CIDA when dragging a Control Panel item

I'm working on a drag and drop problem now and trying to get the PIDLs of the items being dragged from windows shell to my application.
The code below can get correct PIDLs if the dragged item is 'My Computer' or 'Control Panel' itself, but it doesn't work when the dragged item is an item in the 'Control Panel'.
What's wrong with my code?
#define GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])
#define GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])
STGMEDIUM medium;
UINT fmt = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
FORMATETC fe= {fmt, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT GETDATA_RESULT = pDataObject->GetData(&fe, &medium);
if (SUCCEEDED(GETDATA_RESULT))
{
LPIDA pida = (LPIDA)GlobalLock(medium.hGlobal);
LPCITEMIDLIST pidlFolder = GetPIDLFolder(pida);
int n = pida->cidl; // the n is always correct
if( n > 0 )
{
LPCITEMIDLIST pidlItem = GetPIDLItem(pida, 0);
// the pidlItem is wrong when the dragged object is an item in 'Control Panel'
}
GlobalUnlock(medium.hGlobal);
}
ReleaseStgMedium(&medium);
Any idea? Thanks
Zach#Shine
If I D&D Mouse, Network Connections and Fonts I get the following output in my test app:
0 Mouse | sfgao=4 hr=0
1 ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\::{7007ACC7-3202-11D1-AAD2-00805FC1270E} | sfgao=20000004 hr=0
2 C:\WINDOWS\Fonts | sfgao=60000004 hr=0
The Network Connections and Fonts pidls can be converted to fully qualified shell paths while Mouse only returns a relative path/displayname.
This makes sense if you check the documentation for IShellFolder::GetDisplayNameOf:
...They do not guarantee that
IShellFolder will return the requested
form of the name. If that form is not
available, a different one might be
returned. In particular, there is no
guarantee that the name returned by
the SHGDN_FORPARSING flag will be
successfully parsed by
IShellFolder::ParseDisplayName. There
are also some combinations of flags
that might cause the
GetDisplayNameOf/ParseDisplayName
round trip to not return the original
identifier list. This occurrence is
exceptional, but you should check to
be sure.
It is clear that when dealing with controlpanel items, you need to keep the pidl around and only use GetDisplayNameOf for display strings in your UI.
(IShellLink::SetIDList on the Mouse pidl will create a working shortcut so the pidl is valid)
void OnDrop(IDataObject*pDO)
{
STGMEDIUM medium;
UINT fmt = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
FORMATETC fe= {fmt, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hr = pDO->GetData(&fe, &medium);
if (SUCCEEDED(hr))
{
LPIDA pida = (LPIDA)GlobalLock(medium.hGlobal);
if (pida)
{
LPCITEMIDLIST pidlFolder = GetPIDLFolder(pida);
for (UINT i=0; i<pida->cidl; ++i)
{
LPCITEMIDLIST pidlItem = GetPIDLItem(pida,i);
LPITEMIDLIST pidlAbsolute = ILCombine(pidlFolder,pidlItem);
if (pidlAbsolute)
{
IShellFolder*pParentSF;
hr= SHBindToParent(pidlAbsolute,IID_IShellFolder,(void**)&pParentSF,&pidlItem);
if (SUCCEEDED(hr))
{
STRRET str;
hr= pParentSF->GetDisplayNameOf(pidlItem, SHGDN_FORPARSING, &str);
if (SUCCEEDED(hr))
{
TCHAR szName[MAX_PATH];
hr= StrRetToBuf(&str,pidlItem,szName,MAX_PATH);
if (SUCCEEDED(hr))
{
SFGAOF sfgao = SFGAO_FOLDER|SFGAO_FILESYSTEM|SFGAO_HASSUBFOLDER|SFGAO_CANLINK;
hr= pParentSF->GetAttributesOf(1,&pidlItem,&sfgao);
TRACE(_T("%u %s | sfgao=%X hr=%X\n"),i,szName,sfgao,hr);
CreateTestShortcut(pidlAbsolute);
}
}
pParentSF->Release();
}
ILFree(pidlAbsolute);
}
}
GlobalUnlock(medium.hGlobal);
}
ReleaseStgMedium(&medium);
}
}

MFC CFindReplaceDialog destruction

How can I destroy a pointer to CFindReplaceDialog object properly?
For example I have class:
class CjumpView : public CRichEditView
{
CFindReplceDialog *m_pFRDlg;
// ...
};
CjumpView::CjumpView()
: m_pFRDlg(NULL)
{
}
CjumpView::~CjumpView()
{
if(m_pFRDlg != NULL)
{
m_pFRDlg->DestroyWindow();
delete(m_pFRDlg);
}
}
void CjumpView::OnEditFind()
{
if(m_pFRDlg == NULL)
{
const bool fShowFind = true;
m_pFRDlg = new CFindReplaceDialog();
m_pFRDlg->Create(fShowFind, m_sFind, NULL, NULL, this)
}
}
LRESULT CjumpView::OnFind(WPARAM, LPARAM lParam)
{
LPFINDREPLACE lpFindReplace = reinterpret_cast<LPFINDREPLACE>(lParam);
if(lpFindReplace->Flags & FR_DIALOGTERM)
{
m_pFRDlg->DestroyWindow();
delete(m_pFRDlg);
m_pFRDlg = NULL;
return NULL;
}
lpFindReplace->Flags = 0;
return NULL;
}
In Visual Studio CFindReplaceDialog help article it is said that objects of this class should be created in heap using new operator. Then Create member function should be called.
My OnFind function reacts on closing of this Find dialog. It calls DestroyWindow() function, the tries to delete dialog object.
But when I try to call DestoyWindow() in OnFind() or in destructor I have an exception:
Access violation at address...
How to destroy this dialog and to delete pointer?
If someone's interested as me on this problem, the solution is simple.
Actually you don't have to delete CFindReplaceDislog* pointer after it has been used.
After it's closed, it receives WM_NCDESTROY message. And as far as it's derived from CWnd, CWnd::OnNcDestroy() handler is invoked. In the last line it calls PostNcDestroy() which does nothing in CWnd, but overriden in CFindReplaceDialog. There it deletes 'this' pointer like so:
void CFindReplaceDialog::PostNcDestroy()
{
ASSERT(m_hWnd == NULL);
delete this;
}
So, you don't have to invoke delete(m_pFRDlg) anywhere.

Resources