Chinese characters in Title bar - c++

I am creating a Win32 application, ASCII only. However, when I create the window, the title bar shows chinese characters, instead of the intended text:
//registering the window class:
WNDCLASSEXA wc = { };
wc.hInstance = hThisInstance;
wc.lpszClassName = g_classname;
wc.lpfnWndProc = WndPrc;
wc.style = 0;
wc.cbSize = sizeof (WNDCLASSEXA);
wc.hIcon = (HICON) LoadImage(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDI_APPICO), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
wc.hIconSm = (HICON) LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_APPICO),
IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wc.cbClsExtra = 0; /* no extra bytes after the window class */
wc.cbWndExtra = 0; /* structure or the window instance */
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); /*(HBRUSH) GetStockObject(WHITE_PEN);*/
if (!RegisterClassEx(&wc))
return FAIL;
return OK;
g_hwndMain = CreateWindow(g_classname, "Hello World", WS_OVERLAPPEDWINDOW,
g_progsettings.winX,
g_progsettings.winY,
g_progsettings.winWidth,
g_progsettings.winHeight,
0, 0, NULL, 0);
if (!g_hwndMain) {
MessageBox(NULL, "Couldn't make window", "CreateWindowEx",
MB_OK | MB_ICONERROR);
exit(EXIT_FAILURE);
}
if (g_progsettings.winX == -1 && g_progsettings.winY == -1)
centerwin(g_hwndMain);
/* Make the window visible on the screen */
ShowWindow(g_hwndMain, nCmdShow);
UpdateWindow(g_hwndMain);
Here is the titlebar:
When I run the program repeatedly, I still get the same titlebar. UNICODE is not #defined.
Unlike other similar questions, I am not casting a const char * into a LPCWSTR or vice versa, so that shouldn't be the cause of the problem.
Here is my WinMain (a lot of irrelevant details)
INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInstance,LPSTR lpszArgument, int nCmdShow)
{
MSG msg;
HACCEL hAccel;
BOOL msgRet;
INITCOMMONCONTROLSEX icex;
if (signal(SIGSEGV, onSegfault) == SIG_ERR) {
errmsg("Failed to register handler for SIGSEGV", "");
return EXIT_FAILURE;
}
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_STANDARD_CLASSES;
if (InitCommonControlsEx(&icex) == FALSE) {
fmtmsgbox(MB_ICONERROR, "extended common controls err: %s", fmtmsg());
return EXIT_FAILURE;
}
if (winregister(hInst) == FAIL)
errmsg("window class error", "window class");
memset(&g_progsettings, 0, sizeof (settings));
if (g_progsettings.readSettings() == FAIL)
g_progsettings.setDefaults();
mainwindow(hInst, nCmdShow);
hAccel = LoadAccelerators(hInst, MAKEINTRESOURCEA(IDR_ACCEL));
onCreat();
while ((msgRet = GetMessageW(&msg, NULL, 0, 0)) != 0) {
if (msgRet == -1) {
errmsg("GetMessage -1", fmtmsg());
exit(EXIT_FAILURE);
}
if (!g_fd.isdlgmsg(&msg)) {
if (!TranslateAcceleratorW(g_hwndMain, hAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return 0;
}

You are creating an Ansi-based window via RegisterClassExA() and CreateWindowA(), but you are running a Unicode-based message loop by calling GetMessageW() (and TranslateAcceleratorW()) instead of GetMessageA() (and TranslateAcceleratorA()), and then you are using DispatchMessageA() to dispatch those messages. Presumably your WndProc is also calling DefWindowProcA() instead of DefWindowProcW(). So, even though you are creating an Ansi window with an Ansi title, the default window painting is not going to draw the title data correctly when processing Unicode messages as Ansi (or vise versa). You should not mix Ansi and Unicode APIs together when handling your windows. If you create an Ansi window, use an Ansi message loop. If you create a Unicode window (which you should be), use a Unicode message loop.

Related

Minimalist CreateWindowEx fails

this is just a minimalist console application that should show a windows created on the fly :
#include <windows.h>
void main()
{
WNDCLASSEX _c4w = {0};
_c4w.cbSize = sizeof(WNDCLASSEX);
//_c4w.hCursor = ::LoadCursor(0, IDC_APPLICATION);
//_c4w.hIcon = ::LoadIcon(0, IDI_APPLICATION);
_c4w.hInstance = 0;
_c4w.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
_c4w.lpszClassName = "c4w";
HWND _h;
if(!::RegisterClassEx(&_c4w))
{ _h = ::CreateWindowEx( 0, "c4w",
"Minimal Windows Application",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480,
HWND_DESKTOP,
0,
::GetModuleHandle(0), NULL
);
::ShowWindow(_h, SW_SHOW);
}
....
}
unfortunatlity the RegisterClassEx function actually always fails...
I am using C++ Builder 5 and compiling a console Application optioned as MultiThreaded but no VCL...
As #WhozCraig said Your window class doesn't have a wndproc. If you want to use winapi well, please study according to the official documentation. Your program needs a wndproc.
Here is how to create a blank window in MSDN.
Notice that the program does not explicitly call the WindowProc
function, even though we said this is where most of the application
logic is defined. Windows communicates with your program by passing it
a series of messages.
In the code, wc.lpfnWndProc = WindowProc specifies the process callback function.
I understood that a normal Win32 application using HWND and WNDPROC is not what I have done, but here is my solution :
HWND GetSTD()
{ static
HWND _result(0);
static
bool _lock(false);
static
bool _setup(false);
while(_lock) ::Sleep(0);
if(_setup == false)
{ _lock = true;
OSVERSIONINFO _os;
_os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
::GetVersionEx(&_os);
if(_os.dwPlatformId != VER_PLATFORM_WIN32s)
{ char _title[1024];
::GetConsoleTitle(_title, sizeof(_title));
_result = ::FindWindow(0, _title);
if(_os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{ _result = ::GetWindow(_result, GW_CHILD);
if(_result != 0)
{ char _class[128];
::GetClassName(_result, _class, sizeof(_class));
while(::strcmp(_class, "ttyGrab") != 0)
{ _result = ::GetNextWindow(_result, GW_HWNDNEXT);
if(_result != 0)
::GetClassName(_result, _class, sizeof(_class));
}
}
}
}
_setup = true;
_lock = false;
}
return _result;
}
Using the resulting HWND, we could draw over the console with the ::GetDC() and ::ReleaseDC() mechanism...
NB : static variables are used to ensure to return only 1 STD handle per call...

Set a window transparent

I have been trying to set BlueStacks window transparent:
DWORD MakeWindowTransparent(HWND hWnd, unsigned char factor)
{
/* First, see if we can get the API call we need. If we've tried
* once, we don't need to try again. */
if (!initialized)
{
HMODULE hDLL = LoadLibrary(L"user32");
pSetLayeredWindowAttributes =
(PSLWA)GetProcAddress(hDLL, "SetLayeredWindowAttributes");
initialized = TRUE;
}
if (pSetLayeredWindowAttributes == NULL)
return FALSE;
/* Windows need to be layered to be made transparent. This is done
* by modifying the extended style bits to contain WS_EX_LAYARED. */
SetLastError(0);
auto winlong = SetWindowLong(hWnd,
GWL_EXSTYLE,
GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
if ((winlong == 0) && (GetLastError() != 0)) {
auto error = GetLastErrorAsString();
return FALSE;
}
if (!pSetLayeredWindowAttributes(hWnd,RGB(255, 255, 255),factor, LWA_COLORKEY | LWA_ALPHA))
{
auto error = GetLastErrorAsString();
return FALSE;
}
return TRUE;
}
int main() {
HWND hWnd = FindWindowA(NULL, L"BlueStacks");
MakeWindowTransparent(hWnd, 0);
}
BlueStacks can run in opengl and directx, I have tested the code above, using both modes.
MakeWindowTransparent is returning 0
pSetLayeredWindowAttributes auto error = GetLastErrorAsString(); error returned is: wrong parameter.
I have tested the code with other OpenGL windows, and it did not pause in any of the errors, also the window got transparent correctly.
Some information I have collected about the window:
Appreciate any help.
Why are you using both flags LWA_COLORKEY | LWA_ALPHA? If you are specifying a color RGB(255, 255, 255), just use LWA_COLORKEY.
Also, why are you messing with GetProcAddress? SetLayeredWindowAttributes is available starting with Windows 2000; are you targeting platforms older than that?
I am not familiar with BlueStacks, but SetLayeredWindowAttributes to make a window transparent is only working part of the time suggests that SetLayeredWindowAttributes doesn't work with Direct3D; do you know if BlueStacks uses Direct3D?
For OpenGL see this: How to make an OpenGL rendering context with transparent background?
UPDATE
I was playing with that BlueStacks, and figured that you can re-parent it to another window (that's not recommended, as you will need to handle some edge cases). Anyway, I used an existing Notepad window and was able to set alpha on it, and that affected the child BlueStacks window:
int main() {
HWND hWnd = FindWindow(NULL, L"BlueStacks");
HWND hWndN = FindWindow(NULL, L"Untitled - Notepad");
::SetParent(hWnd, hWndN);
auto winlong1 = SetWindowLongPtr(hWnd, GWL_EXSTYLE, 0);
auto winlong2 = SetWindowLongPtr(hWnd, GWL_STYLE, WS_CHILD | WS_VISIBLE);
::SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
MakeWindowTransparent(hWndN, 200);
}
I've also cleaned up your function to get rid of GetProcAddress:
DWORD MakeWindowTransparent(HWND hWnd, unsigned char factor)
{
auto winlong = SetWindowLong(hWnd,
GWL_EXSTYLE,
GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
if ((winlong == 0) && (GetLastError() != 0)) {
return FALSE;
}
if (!SetLayeredWindowAttributes(hWnd, 0, factor, LWA_ALPHA))
{
return FALSE;
}
return TRUE;
}

If I use CreateEx( ... ) after the main window was created I cannot FindWindow( ... )

I have the following code to create a 'message only' window, the window is always created fine, the problem happens when it is created.
Process A
...
auto hInstance = ::GetModuleHandle( nullptr );
WNDCLASSEX wcx;
wcx.cbSize = sizeof(wcx);
wcx.style = 0;
wcx.lpfnWndProc = MyWinProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH);
wcx.lpszMenuName = L"MainMenu";
wcx.lpszClassName = L"MyDummyClass";
wcx.hIconSm = (HICON)LoadImage(hInstance,
MAKEINTRESOURCE(5),
IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
LR_DEFAULTCOLOR);
if (!RegisterClassEx(&wcx))
{
throw "Bad 1.";
}
if (!this->CWnd::CreateEx(0, L"MyDummyClass", L"MyDummyWindow", 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr))
{
throw "Bad 2.";
}
Process B
auto myWnd = FindWindow( L"MyDummyClass");
Now the problem I have is if process A create the window before OnInitDialog is called then process B can find the window.
But if process A creates the window at any other time after the main window was created then process B cannot find the window any longer.
In both cases the message pump is called fine, the window is created as expected, I just cannot FindWindow when I create it after the main application is started.
Why would that be, and how can I work around that?
Use FindWindowEx instead:
To find message-only windows, specify HWND_MESSAGE in the hwndParent
parameter of the FindWindowEx function. In addition, FindWindowEx
searches message-only windows as well as top-level windows if both the
hwndParent and hwndChildAfter parameters are NULL.

Opengl: Rendering to a Win32 API context

I'm trying to create an opengl context (ogl 4.5 at least) and render to it; it works fine with SDL2 but I can't figure out why it doesn't with Win32: I'm trying the screen color to RGBA(1, 0, 0, 1) with glClearColor()/glClear, but nothing seems to happen. Here is my code:
--EDIT I updated the code as you suggested but still, nothing seems rendered; also the problem is not because of gl 3.x/4.x features because I initialized GLEW after having created a wiggle context
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HGLRC ourOpenGLRenderingContext;
bool running = true;
int WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd)
{
MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = L"oglversionchecksample";
wc.style = CS_OWNDC;
if (!RegisterClass(&wc))
return 1;
CreateWindowW(wc.lpszClassName, L"openglversioncheck",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, 0, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0) > 0)
DispatchMessage(&msg);
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
glViewport(0, 0, 100, 100); //render to a viewport of width (100; 100)
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
break;
case WM_CREATE:
{
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags
PFD_TYPE_RGBA, //The kind of framebuffer. RGBA or palette.
32, //Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24, //Number of bits for the depthbuffer
8, //Number of bits for the stencilbuffer
0, //Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE,
0,
0, 0, 0
};
HDC ourWindowHandleToDeviceContext = GetDC(hWnd);
int letWindowsChooseThisPixelFormat;
letWindowsChooseThisPixelFormat = ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd);
SetPixelFormat(ourWindowHandleToDeviceContext, letWindowsChooseThisPixelFormat, &pfd);
ourOpenGLRenderingContext = wglCreateContext(ourWindowHandleToDeviceContext);
wglMakeCurrent(ourWindowHandleToDeviceContext, ourOpenGLRenderingContext);
MessageBoxA(0, (char*)glGetString(GL_VERSION), "OPENGL VERSION", 0);
if(glewInit() != GLEW_OK) {
MessageBoxA(0, (char*)glGetString(GL_VERSION), "Error: Could not init OGL API (GLEW)", 0);
}
}
break;
case WM_CLOSE:
//quit code
wglDeleteContext(ourOpenGLRenderingContext);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Creating a modern OpenGL rendering context in Windows takes a bit more effort. Essentially you first have to create a proxy context to load the necessary extensions, then you create the proper context using those. I wrote a small library that does the internal proxy context housekeeping behind the curtains and lets you get right to the core business without further ado: http://github.com/datenwolf/wglarb
For the sake of StackOverflow best practice of include code in answeres instead of linking here's the main implementation file (it's a mere 238 lines):
/*
Copyright (c) 2014 Wolfgang 'datenwolf' Draxinger
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <GL/gl.h>
#include "wglarb.h"
#define wglarb_BuildAssert(cond) ((void)sizeof(char[1 - 2*!(cond)]))
static HANDLE wglarb_intermediary_mutex = NULL;
static DWORD wglarb_intermediary_lock(void)
{
wglarb_BuildAssert( sizeof(PVOID) == sizeof(HANDLE) );
if( !wglarb_intermediary_mutex ) {
/* Between testing for the validity of the mutex handle,
* creating a new mutex handle and using the interlocked
* exchange there is a race... */
/* //// START \\\\ */
HANDLE const new_mutex =
CreateMutex(NULL, TRUE, NULL);
HANDLE const dst_mutex =
InterlockedCompareExchangePointer(
&wglarb_intermediary_mutex,
new_mutex,
NULL );
/* //// FINISH \\\\ */
if( !dst_mutex ) {
/* mutex created in one time initialization and held
* by calling thread. Return signaled status. */
return WAIT_OBJECT_0;
}
/* In this case we lost the race and another thread
* beat this thread in creating a mutex object.
* Clean up and wait for the proper mutex. */
ReleaseMutex(new_mutex);
CloseHandle(new_mutex);
}
return WaitForSingleObject(wglarb_intermediary_mutex, INFINITE);
}
static BOOL wglarb_intermediary_unlock(void)
{
return ReleaseMutex(wglarb_intermediary_mutex);
}
#define WGLARB_INTERMEDIARY_CLASS "wglarb intermediary"
#define WGLARB_INTERMEDIARY_STYLE (WS_CLIPSIBLINGS|WS_CLIPCHILDREN)
#define WGLARB_INTERMEDIARY_EXSTYLE 0
static HWND wglarb_intermediary_hWnd = 0;
static BOOL wglarb_intermediary_create_Wnd(void)
{
HINSTANCE const hInstance = GetModuleHandle(NULL);
WNDCLASS wc;
memset(&wc,0,sizeof(wc));
wc.hInstance = hInstance;
wc.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
wc.lpfnWndProc = DefWindowProc;
wc.lpszClassName = WGLARB_INTERMEDIARY_CLASS;
RegisterClass(&wc);
wglarb_intermediary_hWnd =
CreateWindowEx(
WGLARB_INTERMEDIARY_EXSTYLE,
WGLARB_INTERMEDIARY_CLASS,
NULL,
WGLARB_INTERMEDIARY_STYLE,
0,0,0,0,
NULL,NULL,
hInstance,
NULL );
if( !wglarb_intermediary_hWnd ) {
return FALSE;
}
return TRUE;
}
static HDC wglarb_intermediary_hDC = 0;
static BOOL wglarb_intermediary_create_DC(void)
{
if( !wglarb_intermediary_hWnd
&& !wglarb_intermediary_create_Wnd() ) {
return FALSE;
}
wglarb_intermediary_hDC = GetDC(wglarb_intermediary_hWnd);
if( !wglarb_intermediary_hDC ) {
return FALSE;
}
return TRUE;
}
static HGLRC wglarb_intermediary_hRC = 0;
static BOOL wglarb_intermediary_create_RC(void)
{
if( !wglarb_intermediary_hDC
&& !wglarb_intermediary_create_DC() ) {
return FALSE;
}
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd,0,sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL|PFD_GENERIC_ACCELERATED|PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
int iPF;
if( !(iPF = ChoosePixelFormat(wglarb_intermediary_hDC, &pfd))
|| !(SetPixelFormat(wglarb_intermediary_hDC, iPF, &pfd))
|| !(wglarb_intermediary_hRC = wglCreateContext(wglarb_intermediary_hDC))
) {
return FALSE;
}
return TRUE;
}
static BOOL wglarb_intermediary_makecurrent(HDC *hOrigDC, HGLRC *hOrigRC)
{
*hOrigDC = wglGetCurrentDC();
*hOrigRC = wglGetCurrentContext();
if( !wglarb_intermediary_hRC
&& !wglarb_intermediary_create_RC() ) {
return FALSE;
}
return wglMakeCurrent(wglarb_intermediary_hDC, wglarb_intermediary_hRC);
}
HGLRC WINAPI wglarb_CreateContextAttribsARB(
HDC hDC,
HGLRC hShareContext,
const int *attribList)
{
if( WAIT_OBJECT_0 != wglarb_intermediary_lock() ) {
return NULL;
}
HDC hOrigDC;
HGLRC hOrigRC;
if( !wglarb_intermediary_makecurrent(&hOrigDC, &hOrigRC) ) {
wglarb_intermediary_unlock();
return NULL;
}
PFNWGLCREATECONTEXTATTRIBSARBPROC impl =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
HGLRC ret = NULL;
if( impl ) {
ret = impl(hDC, hShareContext, attribList);
}
wglMakeCurrent(hOrigDC, hOrigRC);
wglarb_intermediary_unlock();
return ret;
}
BOOL WINAPI wglarb_ChoosePixelFormatARB(
HDC hdc,
const int *piAttribIList,
const FLOAT *pfAttribFList,
UINT nMaxFormats,
int *piFormats,
UINT *nNumFormats)
{
if( WAIT_OBJECT_0 != wglarb_intermediary_lock() ) {
return FALSE;
}
HDC hOrigDC;
HGLRC hOrigRC;
if( !wglarb_intermediary_makecurrent(&hOrigDC, &hOrigRC) ) {
wglarb_intermediary_unlock();
return FALSE;
}
PFNWGLCHOOSEPIXELFORMATARBPROC impl = NULL;
impl = (PFNWGLCHOOSEPIXELFORMATARBPROC)
wglGetProcAddress("wglChoosePixelFormatARB");
if( !impl ) {
/* WGL_EXT_pixel_format uses the same function prototypes
* as the WGL_ARB_pixel_format extension */
impl = (PFNWGLCHOOSEPIXELFORMATARBPROC)
wglGetProcAddress("wglChoosePixelFormatEXT");
}
BOOL ret = FALSE;
if( impl ) {
ret = impl(
hdc,
piAttribIList,
pfAttribFList,
nMaxFormats,
piFormats,
nNumFormats );
}
wglMakeCurrent(hOrigDC, hOrigRC);
wglarb_intermediary_unlock();
return ret;
}
Look at the code for SDL to see what it does - I think there's some faffing about to get a context with modern (>=3 or >=4) OpenGL.
https://www.opengl.org/wiki/Creating_an_OpenGL_Context_%28WGL%29

Creating window in another thread(not main thread)

I've got a function:
HWND createMainWindow(P2p_Socket_Machine * toSend){
HWND hMainWnd = CreateWindow(
L"Class",/*(LPCWSTR) nameOfConference.c_str()*/L"Chat", WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU,
CW_USEDEFAULT, 0, 600,400,
(HWND)NULL, (HMENU)NULL,
/*(HINSTANCE)hlnstance*/NULL, NULL
);
if (!hMainWnd) {
MessageBox(NULL, L"Cannot create main window", L"Error", MB_OK);
return 0;
}
CreateWindowA("LISTBOX",NULL, WS_CHILD|WS_VISIBLE|WS_BORDER|WS_VSCROLL|LBS_NOTIFY|LBS_MULTIPLESEL,310,30,255,275,hMainWnd,(HMENU)List_Box,NULL,NULL);
CreateWindowExA(NULL,"BUTTON", "Refresh", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,385,310,100,24,hMainWnd,(HMENU)Button_Refresh, NULL ,NULL);
CreateWindowExA(NULL,"BUTTON", "Send", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,385,334,100,24,hMainWnd,(HMENU)Button_Send, NULL ,NULL);
CreateWindowExA(NULL,"BUTTON", "New", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,385,354,100,24,hMainWnd,(HMENU)Button_New, NULL ,NULL);
CreateWindowA("EDIT",0,WS_BORDER|WS_VISIBLE|WS_CHILD|ES_LEFT|ES_MULTILINE|WS_VSCROLL|WS_DISABLED,
10,30,265,275,hMainWnd,(HMENU)Text_Box_Get,NULL,NULL);
CreateWindowA("EDIT",0,WS_BORDER|WS_VISIBLE|WS_CHILD|ES_LEFT|ES_MULTILINE|WS_VSCROLL,
10,320,265,45,hMainWnd,(HMENU)Text_Box_Send,NULL,NULL);
SetWindowLongPtr(hMainWnd,GWLP_USERDATA,(LONG_PTR)toSend);
ShowWindow(hMainWnd, SW_SHOW);
//UpdateWindow(hMainWnd);
return hMainWnd;
}
And this is main part of my program:
int WINAPI WinMain(HINSTANCE hlnstance, HINSTANCE hPrevInstance, LPSTR IpCmdLine, int
nCmdShow)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MyFunc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hlnstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"Class";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
HWND toSend = createMainWindow(P2pSocket);
//some code
hThread = CreateThread(NULL, 0, ClientThread,
Message2, 0, &dwThreadId);
if (hThread == NULL)
{
cout<<"Create thread filed";
exit(10);
}
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
When i call function createMainWindow() in main part of my program
it works as it should, but when i run it in
my thread(ClientThread) it doesn't work. i've read that i should create windows only in main thread. Is it true? And if it's true, what is the simplest way to call this function from another thead to be done in main thread?
Thanks everyone. Now i know the problem, but i'm stuck with solution.
My client thread code is:
while(1){
vector<HWND> AllHandlers;
pair<string,string> Answer = Pointer->receiveMsgByUdp();
if(!Pointer->isMyLocalAddress(Answer.first)){
int type = messageUdpContentType(Answer.second);
switch(type){
case 0 :
Pointer->sendMsgToIpUdp(Answer.first,"<?xml version='1.0'?><accepted/>");
AllHandlers = getAllHandlersOfElementsOnWindowsByIdentityCode(Pointer->getAllHandlers(),List_Box);
for(vector<HWND>::iterator j = AllHandlers.begin();j!=AllHandlers.end();j++)
if(SendMessageA(*j, LB_FINDSTRINGEXACT, 0, (LPARAM)Answer.first.c_str())==LB_ERR)
SendMessageA(*j, LB_ADDSTRING, 0, (LPARAM)Answer.first.c_str());
break;
case 1 :
AllHandlers = getAllHandlersOfElementsOnWindowsByIdentityCode(Pointer->getAllHandlers(),List_Box);
for(vector<HWND>::iterator j = AllHandlers.begin();j!=AllHandlers.end();j++)
if(SendMessageA(*j, LB_FINDSTRINGEXACT, 0, (LPARAM)Answer.first.c_str())==LB_ERR)
SendMessageA(*j, LB_ADDSTRING, 0, (LPARAM)Answer.first.c_str());
break;
case 2 :
AllHandlers = getAllHandlersOfElementsOnWindowsByIdentityCode(Pointer->getAllHandlers(),List_Box);
for(vector<HWND>::iterator j = AllHandlers.begin();j!=AllHandlers.end();j++)
if((i = SendMessageA(*j, LB_FINDSTRINGEXACT, 0, (LPARAM)Answer.first.c_str()))!=LB_ERR)
SendMessageA(*j,LB_DELETESTRING, 0, (LPARAM)Answer.first.c_str());
break;
case 3 :
userReply = MessageBoxW(NULL, L"Принять приглашение на конференцию?",
L"", MB_YESNO | MB_ICONQUESTION);
if (userReply==IDYES){
//todo: Проверка на создание встречи, в которой уже состоишь
string nameOfConf = fetchNameOfInviteConf(Answer.second);
Pointer->createConference(nameOfConf);
HWND toSendTo = createMainWindow(Pointer);
Pointer->setHandlerInfo(nameOfConf,toSendTo);
Pointer->addNewMemberToConference_ServerType(nameOfConf,Answer.first);
string toSend = string("<?xml version='1.0'?><inviteAccepted>") + nameOfConf + string("</inviteAccepted>");
Pointer->sendMsgToIpUdp(Answer.first,toSend);
}
break;
case 4 :
string nameOfConf = fetchNameOfInviteAcceptConf(Answer.second);
toSend.clear();
Participants.clear();
Participants = Pointer->getCurrentParticipants(nameOfConf);
toSend+="<?xml version='1.0'?>";
toSend+="<conference>";
toSend+="<nameOfConference>";
toSend+=nameOfConf;
toSend+="</nameOfConference>";
for(vector<string>::iterator i = Participants.begin();i!=Participants.end();i++){
toSend+="<participant>" + *i + "</participant>";
}
toSend+="</conference>";
Pointer->addNewMemberToConference_ClientType(nameOfConf,Answer.first);
Pointer->sendToIpTcp(Answer.first,toSend);
break;
}
the function receiveMsgByUdp() stops this thread until receives message. I apologize for lack of knowledge, but what functions can i use or another stuff to solve this. Should i rewrite my method receiveMsgByUdp() to be asynchronous or how can i call function createMainWindow() to be run on main thread?About the last variant : how can i do this in pure winapi, i couldn't found any simple examples. Can someone give code snippet. Thanks one more time)
You can indeed create windows in threads other than the main UI thread. However, those windows will have affinity to the thread that created them and you will need to run a message pump in each and every thread that creates windows.
So whilst you can do what you ask, Win32 is really designed to work with all windows in a process having affinity to the same thread. There's really nothing to be gained from creating multiple UI threads. All you will succeed in doing is making your life extraordinarily and needlessly complex.
You can create windows on "non-main" threads but be aware that those windows are attached to the creation thread, and you need to make sure to implement a message loop there and keep dispatching messages posted on the queue. If you don't do this, your windows are going to freeze.
See:
Using Messages and Message Queues
Message Handling -- About Messages and Message Queues
The system does not automatically create a message queue for each
thread. Instead, the system creates a message queue only for threads
that perform operations which require a message queue. If the thread
creates one or more windows, a message loop must be provided; this
message loop retrieves messages from the thread's message queue and
dispatches them to the appropriate window procedures.
If you create a window in another thread, you will also need to implement a message loop on that thread since queued messages are posted to the message queue of thread which owns the window.