How do I get rid of flicker with STM_SETIMAGE - winapi

We have updated our windows code to use Styles and since then we get a flicker in various parts of the code when using STM_SETIMAGE to update a bitmap on a window.
I have created a minimal reproducible example here. Can anyone tell me what I need to do to get rid of the flicker please ?
The code simply redraws a bitmap every 1/100 second and calls the windows function to set the image onto the window. It worked without a flicker before we added Windows Styles.
Thanks
Shaun
#include <windows.h>
#include <CommCtrl.h>
#include <math.h>
#include <objbase.h>
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
//--------------------------------------
#ifndef HINST_THISCOMPONENT
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
#endif
//--------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hwnd, message, wParam, lParam);
}
//--------------------------------------
HWND logo;
HWND m_hwnd;
HBITMAP testBitmap;
int counter=0;
typedef unsigned char u8;
typedef unsigned int u32;
//--------------------------------------
HRESULT App_Initialize()
{
HRESULT hr;
// Register the window class.
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);;
wcex.lpszMenuName = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.lpszClassName = TEXT("myApp");
RegisterClassEx(&wcex);
int dpiX = 0;
int dpiY = 0;
HDC hdc = GetDC(NULL);
if (hdc)
{
dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(NULL, hdc);
}
m_hwnd = CreateWindow( TEXT("myApp"), TEXT("Simple Set image Example"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 640, 640, NULL,NULL,HINST_THISCOMPONENT,0);
hr = m_hwnd ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
ShowWindow(m_hwnd, SW_SHOWNORMAL);
UpdateWindow(m_hwnd);
}
logo = CreateWindow("Static", NULL, SS_BITMAP | WS_CHILD | WS_VISIBLE, 40, 40,512,512, m_hwnd, NULL, NULL, NULL);
return hr;
}
//----------------------------------------------
void Redraw()
{
DeleteObject(testBitmap);
testBitmap=0;
u8 * RenderImageData=(u8*)malloc(512*512*4);
u32 * p=(u32*)RenderImageData;
for(int i=0;i<512;i++)
{
p[i+counter*512]=0xff000000;
p[i*512+counter]=0xff000000;
}
testBitmap = CreateBitmap(512,512, 4, 8, RenderImageData);
SendMessage(logo,STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) testBitmap);
free(RenderImageData);
counter=(counter+1)&511;
}
//----------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance ,HINSTANCE hPrevInstance ,LPSTR lpCmdLine ,int nCmdShow)
{
if (SUCCEEDED(CoInitialize(NULL)))
{
if (SUCCEEDED(App_Initialize()))
{
MSG msg;
while(1)
{
while (PeekMessage(&msg, NULL, 0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(10);
Redraw();
}
}
CoUninitialize();
}
return 0;
}
//----------------------------------------------

I found this code which seems to work.
Instead of
HBITMAP hbm=(HBITMAP)SendMessage(hWndPic,STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) pD->hbitmap);
I call
GDI_SetImageX(pD->hbitmap,hWndPic, xs, ys);
void GDI_SetImageX( HBITMAP hBM, HWND hCtrl , int w, int h)
{
HDC hdcSrc=CreateCompatibleDC(0);
HDC hdcDst=GetDC(hCtrl);
HGDIOBJ hbmOld=SelectObject(hdcSrc,hBM);
HGDIOBJ hbmNew=CreateBitmap(w,h,4,8,0);
HGDIOBJ hbmOld2=SelectObject(hdcDst,hbmNew);
BitBlt(hdcDst,0,0,w,h,hdcSrc,0,0,0x00cc0020);
SelectObject(hdcSrc,hbmOld);
DeleteDC(hdcSrc);
ReleaseDC(hCtrl,hdcDst);
SendMessage(hCtrl,0x0b,0,0);
LRESULT oBM=SendMessage(hCtrl,STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hBM);
SendMessage(hCtrl,0x0b,1,0);
DeleteObject(hBM);
}

Related

How do I select item based on typed letters on owner-draw combobox?

On a regular combobox, you can jump to items that starts with the typed letter. e.g., if you have items like "baa", "arch", "foo", "art" and type "a" the item "arch" gets selected, you type "a" again then it jumps to "art". How can I implement this on owner-draw combobox? I thought I could handle WM_CHAR like below in the comobobox's subprocedure, however I couldn't even test it, since setting a procedure to the comobobox like that fails:
HWND hwndEdit = GetWindow(hwndCombo, GW_CHILD);
assert(hwndEdit != NULL); // fails here
lpfnEditWndProc = (WNDPROC) SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR) SubClassProc);
the procecdure was going to be like this:
LRESULT CALLBACK SubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CHAR:
{
static int prevIndex = 0;
static wchar_t buffer[2] = {0};
memset(&buffer, 0, sizeof(buffer));
buffer[0] = wParam;
prevIndex = SendMessage(hwndCombo, CB_FINDSTRING, (WPARAM) prevIndex, (LPARAM) buffer);
SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) prevIndex, 0);
return 0;
}
break;
}
return CallWindowProc(lpfnEditWndProc, hwnd, msg, wParam, lParam);
}
Here's the full code of owner-draw combobox:
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")
#pragma comment(lib, "UxTheme.lib")
#pragma comment(lib, "Comdlg32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <Commctrl.h>
#include <assert.h>
#include <uxtheme.h>
#include <Commdlg.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void SetDefaultFont(HWND hwnd);
HFONT LoadSystemDefaultFont();
void DrawBorder(HDC hdc, RECT *rect);
void DrawLine(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2);
void freeBrushes();
HBRUSH getBrushAt(int index);
void drawColorRect(HDC dc, RECT *editRect, int colorIndex);
void EnableVisualStyles2(void);
LRESULT CALLBACK SubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
HINSTANCE g_hinst;
HFONT hDefaultSystemFont;
HWND hwndCombo;
#define COUNTOF(a) (sizeof(a)/sizeof(a[0]))
#define LIST \
X(L"Black", RGB(0, 0, 0)) \
X(L"Red", RGB(255, 0, 0)) \
X(L"Blue", RGB(0, 0, 255)) \
X(L"Green", RGB(0, 128, 0)) \
X(L"Yellow", RGB(255, 255, 0))
#define X(a, b) a,
const wchar_t *items[] = { LIST };
#undef X
#define X(a, b) b,
const int colorCodes[] = { LIST };
#undef X
HBRUSH brushes[COUNTOF(items)];
WNDPROC lpfnEditWndProc;
enum
{
BTN_A = 20,
BTN_COMBO,
};
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR lpCmdLine, int nCmdShow) {
HWND hwnd;
MSG msg;
WNDCLASSW wc = {0};
wc.lpszClassName = L"Application";
wc.hInstance = hInstance ;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0,IDC_ARROW);
g_hinst = hInstance;
RegisterClassW(&wc);
hwnd = CreateWindowW(wc.lpszClassName, L"Combo box",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 270, 170, 0, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0)) {
DispatchMessage(&msg);
}
DeleteObject(hDefaultSystemFont);
freeBrushes();
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
hwndCombo = CreateWindow(L"Combobox", NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST |
CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL,
10, 10, 100, 110, hwnd, (HMENU) BTN_COMBO, g_hinst, NULL);
SendMessage(hwndCombo, CB_SETMINVISIBLE, 5, 0);
SetDefaultFont(hwndCombo);
COMBOBOXINFO ci = {0};
ci.cbSize = sizeof(COMBOBOXINFO);
GetComboBoxInfo(hwndCombo, &ci);
lpfnEditWndProc = (WNDPROC)SetWindowLongPtr(ci.hwndList, GWLP_WNDPROC, (LONG_PTR)SubClassProc);
for (int i = 0; i < COUNTOF(items); ++i)
{
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) items[i]);
}
}
break;
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT b = (LPDRAWITEMSTRUCT) lParam;
SetBkMode(b->hDC, TRANSPARENT);
if(b->itemState & ODS_SELECTED)
{
FillRect(b->hDC, &b->rcItem, (HBRUSH) (COLOR_HIGHLIGHT+1));
SetTextColor(b->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT+1));
}
else
{
FillRect(b->hDC, &b->rcItem, (HBRUSH) (COLOR_WINDOW+1));
SetTextColor(b->hDC, GetSysColor(COLOR_WINDOWTEXT+1));
}
if(b->itemID != -1)
{
drawColorRect(b->hDC, &b->rcItem, b->itemID);
DrawText(b->hDC, items[b->itemID], -1, &b->rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
if(b->itemAction & ODA_FOCUS)
{
DrawFocusRect(b->hDC, &b->rcItem);
}
return (INT_PTR) TRUE;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
HFONT LoadSystemDefaultFont()
{
if(hDefaultSystemFont == NULL) {
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
hDefaultSystemFont = CreateFontIndirect(&ncm.lfMessageFont);
}
return hDefaultSystemFont;
}
void SetDefaultFont(HWND hwnd)
{
SendMessage(hwnd, WM_SETFONT, (LPARAM) LoadSystemDefaultFont(), TRUE);
}
void drawColorRect(HDC dc, RECT *editRect, int colorIndex)
{
assert(colorIndex >= 0 && colorIndex < COUNTOF(brushes));
assert(editRect != NULL);
RECT rt = {0};
rt.left = editRect->left + 2;
rt.top = editRect->top - 2;
rt.right = editRect->right / 5;
rt.bottom = editRect->bottom - 2;
InflateRect(&rt, -1, -1);
DrawBorder(dc, &rt);
//FrameRect(dc, &rt, getBrushAt(0));
FillRect(dc, &rt, getBrushAt(colorIndex));
}
void DrawLine(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2)
{
MoveToEx(hdc, x1, y1, NULL);
LineTo(hdc, x2, y2);
}
void DrawBorder(HDC hdc, RECT *rect)
{
DrawLine(hdc, rect->left, rect->top, rect->left, rect->bottom);
DrawLine(hdc, rect->left, rect->top, rect->right, rect->top);
DrawLine(hdc, rect->right, rect->top, rect->right, rect->bottom);
DrawLine(hdc, rect->left, rect->bottom, rect->right, rect->bottom);
}
HBRUSH getBrushAt(int index)
{
assert(index >= 0 && index < COUNTOF(brushes));
HBRUSH b = brushes[index];
if(b == NULL) {
int code = colorCodes[index];
brushes[index] = CreateSolidBrush(code);
b = brushes[index];
}
return b;
}
void freeBrushes()
{
for(int i = 0; i < COUNTOF(brushes); ++i){
DeleteObject(brushes[i]);
brushes[i] = NULL;
}
}
void EnableVisualStyles2(void)
{
TCHAR dir[MAX_PATH] = {0};
GetSystemDirectory(dir, sizeof(dir) / sizeof(*dir));
ACTCTX actCtx = {0};
actCtx.cbSize = sizeof(ACTCTX);
actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID |
ACTCTX_FLAG_SET_PROCESS_DEFAULT |
ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
actCtx.lpSource = L"shell32.dll";
actCtx.lpAssemblyDirectory = dir;
actCtx.lpResourceName = (LPCTSTR) 124;
ULONG_PTR cookie = FALSE;
HANDLE h = CreateActCtx(&actCtx);
assert(h != INVALID_HANDLE_VALUE);
ActivateActCtx(h, &cookie);
}
LRESULT CALLBACK SubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CHAR:
{
static int prevIndex = 0;
static wchar_t buffer[2] = {0};
buffer[0] = wParam;
MessageBox(NULL, buffer, L"", MB_OK);
prevIndex = SendMessage(hwndCombo, CB_FINDSTRING, (WPARAM) prevIndex, (LPARAM) buffer);
SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) prevIndex, 0);
return 0;
}
break;
}
return CallWindowProc(lpfnEditWndProc, hwnd, msg, wParam, lParam);
}
UPDDATE sorry, I past the code sample from other file than the owner-draw combobox. As pointed out by #Song Zhu - MSFT, set the procedure to properly but that still doesn't process WM_CHAR.
The drop-down COMBOBOX does not have an EDIT control. Instead, it has a drop-down list.
I recommend you to use GetComboBoxInfo to get the child window of the COMBOBOX control.
Try to modify the code as:
COMBOBOXINFO ci{};
ci.cbSize = sizeof(COMBOBOXINFO);
GetComboBoxInfo(hwndCombo, &ci);
lpfnEditWndProc = (WNDPROC)SetWindowLongPtr(ci.hwndList, GWLP_WNDPROC, (LONG_PTR)SubClassProc);
Of course, you can use this code to see that hwndItem of COMBOBOXINFO returns NULL. You can adjust which handle you need to control according to your combobox type.
Edit:
Your message loop code and setting style are wrong(need CBS_HASSTRINGS), please refer to:
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
......
hwndCombo = CreateWindow(L"Combobox", NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST |
CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL | CBS_HASSTRINGS,
10, 10, 100, 110, hwnd, (HMENU) BTN_COMBO, g_hinst, NULL);

Create a openGl context (new version)

i was trying to create a win32 that could handle openGl ( the new version). It doesnt seem to be mutch info about win32/opengl(new version, most examples are in the old version ) on the net.
The few info that i found lead me to this code. But it doesnt display the square.
Does any one know if this is the proper way to do it, and if so what is wrong with it(it doesnt display square).
Ps. i know that the part of the vbo, vao ,shader.. are working cause i already did that with sdl.
Thank a lot.... :)
Here is the Code:
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <glew.h>
#include <wglew.h>
using namespace std;
void display(){
// display square
}
bool progRun = false;
//-------------------------------------------------------------------
//#####################################################################
//-------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
){
WNDCLASSEX wcex;
///////////////////////////LOAD GLEW///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS ;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = NULL;
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,"RegisterClassEx","ERROR",MB_OK|MB_ICONSTOP);
return 0;
}
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 500,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,"hWnd","ERROR",MB_OK|MB_ICONSTOP);
return -1;
}
HDC hdc = GetDC(hWnd);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize= sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
int pf = ChoosePixelFormat(hdc, &pfd);
if(pf == 0){
MessageBox(NULL,"pf == 0","ERROR",MB_OK|MB_ICONSTOP);
return -1;
}
if(SetPixelFormat(hdc, pf, &pfd) == false){
MessageBox(NULL,"SetPixelFormat","ERROR",MB_OK|MB_ICONSTOP);
return -1;
}
DescribePixelFormat(hdc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
HGLRC hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);
glewExperimental = true;
if(glewInit() != GLEW_OK){
MessageBox(NULL, "Couldn't initialize GLEW!", "Fatal Error", MB_ICONERROR);
}
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hdc);
wglDeleteContext(hrc);
DestroyWindow(hWnd);
///////////////////////////////TO_CREATE A OPENGL CONTEXT WITH LATER VERSION///////////////////////////////////////
//////////////////////////////////////////////////////////////////////
#define iMajorVersion 3
#define iMinorVersion 1
hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 500,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,"hWnd","ERROR",MB_OK|MB_ICONSTOP);
return -1;
}
hdc = GetDC(hWnd);
bool bError = false;
if(iMajorVersion <= 2)
{
cout << "version 2" <<endl;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
pf = ChoosePixelFormat(hdc, &pfd);
if (pf == 0){
MessageBox(NULL,"pf == 0","ERROR",MB_OK|MB_ICONSTOP);
return false;
}
if(!SetPixelFormat(hdc, pf, &pfd)){
MessageBox(NULL,"SetPixelFormat 1","ERROR",MB_OK|MB_ICONSTOP);
return false;
}
// Create the old style context (OpenGL 2.1 and before)
hrc = wglCreateContext(hdc);
if(hrc)wglMakeCurrent(hdc, hrc);
else bError = true;
}
else if(WGLEW_ARB_create_context && WGLEW_ARB_pixel_format)
{
cout << "version 3" <<endl;
const int iPixelFormatAttribList[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0 // End of attributes list
};
int iContextAttribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, iMajorVersion,
WGL_CONTEXT_MINOR_VERSION_ARB, iMinorVersion,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0 // End of attributes list
};
int iNumFormats;
if(!wglChoosePixelFormatARB(hdc, iPixelFormatAttribList, NULL, 1, &pf, (UINT*)&iNumFormats)){
MessageBox(NULL,"wglChoosePixelFormatARB","ERROR",MB_OK|MB_ICONSTOP);
return 0;
}
// PFD seems to be only redundant parameter now
if(!SetPixelFormat(hdc, pf, &pfd)){
MessageBox(NULL,"SetPixelFormat 2","ERROR",MB_OK|MB_ICONSTOP);
return false;
}
hrc = wglCreateContextAttribsARB(hdc, 0, iContextAttribs);
// If everything went OK
if(hrc) wglMakeCurrent(hdc, hrc);
else bError = true;
//glewInit();
}else{
bError = true;
}
if(bError)
{
// Generate error messages
char sErrorMessage[255], sErrorTitle[255];
sprintf(sErrorMessage, "OpenGL %d.%d is not supported! Please download latest GPU drivers!", iMajorVersion, iMinorVersion);
sprintf(sErrorTitle, "OpenGL %d.%d Not Supported", iMajorVersion, iMinorVersion);
MessageBox(hWnd, sErrorMessage, sErrorTitle, MB_ICONINFORMATION);
return false;
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
MSG msg;
progRun = true;
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//-----------Setup shader and objects
setupShader();
setupObject();
//-------
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL);
glClearColor(1,0,0,1);
while(progRun){
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
glClear(GL_COLOR_BUFFER_BIT);
display();
SwapBuffers(hdc);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message){
case WM_ERASEBKGND:
display();
break;
case WM_PAINT:
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_SIZE:
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
break;
case WM_DESTROY:
PostQuitMessage(0);
progRun = false;
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
If you use wglCreateContext then you get old context (<= 2.1).
You need wglCreateContextAttribsARB instead. But this first you need to get a pointer to this function, which requires using a context.
So:
Create a normal, old context, and set it current. Any pixelformat is
valid.
Get the pointers to wglCreateContextAttribsARB (and perhaps also for wglChoosePixelFormatARB), by using
wglGetProcAddress. Now you can delete the old context.
Set the pixelformat you wish and the context attributes you wish.
Create the context by that pointer.
Useful links from the wiki OpenGL are here and here and here

Is there a way to get the handle of the entry field in a date time picker (DTP)?

The DATETIMEPICKERINFOstructure obtained by sending the DTM_GETDATETIMEPICKERINFOmessage has a field hwndEdit which might be what I'm looking for. However, I'm getting always NULL for it so I'm wondering what's its actual meaning. If not, is there a way to get the handle of the entry field?
hwndEdit only seems to be valid when the control has the DTS_APPCANPARSE style and you click the date text with the mouse (I tested this with OutputDebugString and a timer). The edit control is created and destroyed dynamically. The hwndUD handle is only valid if DTS_UPDOWN is set and the hwndDropDown is only valid while the dropdown is visible.
It is not called out in the documentation but DTM_GETDATETIMEPICKERINFO is marked Vista+ and this often means the feature is only implemented in ComCtl32 v6 so you also have to make sure you have a manifest that requests this version.
To change the color you can try DTM_SETMCCOLOR but only MCSC_BACKGROUND is documented to work when Visual Styles are active.
I'm afraid there is no way to get what you wanted. I just created a simple Win32 application just to test the possibility. If I use the DTM_GETDATETIMEPICKERINFO, hwndDropDown, hwndEdit and hwndUD give me NULL. If I try to enum child window, well before I do so I check it with Spy++, no luck, there is no child window associated with it.
Finally, I tried GetFocus() and WindowFromPoint(), both give me the HWND of the DateTimePicker itself only.
Here is my testing code:
#pragma comment(lib, "comctl32.lib")
#include <windows.h>
#include <tchar.h>
#include <commctrl.h>
enum MYID {
MYID_FIRST = WM_APP,
MYID_DTP
};
LPCTSTR const g_MyWndClass = _T("DTPTest");
LPCTSTR const g_MyWndTitle = _T("DTPTest");
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void OnWindowCreate(HWND);
void OnTimer(HWND);
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int nCmdShow)
{
INITCOMMONCONTROLSEX icex{};
icex.dwSize = sizeof(icex);
icex.dwICC = ICC_DATE_CLASSES;
InitCommonControlsEx(&icex);
WNDCLASSEX wcex{};
wcex.cbSize = sizeof(wcex);
wcex.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.lpfnWndProc = WndProc;
wcex.lpszClassName = g_MyWndClass;
wcex.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wcex);
HWND hwnd = CreateWindowEx(0,
g_MyWndClass, g_MyWndTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 600, 400,
nullptr, nullptr, nullptr, nullptr);
if (!hwnd) { return 99; }
SetTimer(hwnd, 0, 100, nullptr);
ShowWindow(hwnd, nCmdShow);
MSG msg{};
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
{
switch (msg) {
case WM_CREATE:
OnWindowCreate(hwnd);
break;
case WM_TIMER:
OnTimer(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, w, l);
}
return 0;
}
void OnWindowCreate(HWND hwnd)
{
HWND hwndDTP = CreateWindowEx(0, DATETIMEPICK_CLASS, nullptr,
WS_CHILD | WS_VISIBLE | DTS_SHOWNONE,
20, 50, 220, 20,
hwnd, reinterpret_cast<HMENU>(MYID_DTP), nullptr, nullptr);
DATETIMEPICKERINFO info{};
info.cbSize = sizeof(DATETIMEPICKERINFO);
SendMessage(hwndDTP, DTM_GETDATETIMEPICKERINFO, 0,
reinterpret_cast<LPARAM>(&info));
if (!info.hwndDropDown && !info.hwndEdit && !info.hwndUD)
{
MessageBox(hwnd, _T("No luck with DTM_GETDATETIMEPICKERINFO"),
nullptr, MB_ICONERROR);
}
}
void OnTimer(HWND hwnd)
{
POINT pt{};
GetCursorPos(&pt);
HWND hwndPoint = WindowFromPoint(pt);
HWND hwndFocus = GetFocus();
TCHAR buf[99]{};
wsprintf(buf, _T("Pointing at %p, focusing %p"),
hwndPoint, hwndFocus);
SetWindowText(hwnd, buf);
}

Display of Malayalam symbol changes when the selection changes

When I move the selection, character spacing and characters themselves change.
Test project code:
#include <windows.h>
#include <Richedit.h>
class RichEditLib
{
HMODULE lib;
public:
RichEditLib()
{
lib = ::LoadLibrary(L"riched20.dll");
}
~RichEditLib()
{
if (lib) ::FreeLibrary(lib);
}
} libraryLoader;
class RichEdit
{
public:
RichEdit(HWND parent)
{
hwnd = ::CreateWindowEx (
NULL, // extended window style
RICHEDIT_CLASSW, // name of a registered window class
L"", // window caption
WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP |
WS_VSCROLL | ES_LEFT |ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL, // window style
0, // x position
0, // y position
400, // width
400, // height
parent, // handle to owner window
NULL, // handle to menu
::GetModuleHandle(NULL), // application instance
NULL);
::ShowWindow(hwnd, SW_SHOW);
}
~RichEdit()
{
if (hwnd) ::DestroyWindow(hwnd);
}
private:
HWND hwnd;
};
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:
::PostQuitMessage(0);
break;
default:
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
HWND CreateMainWindow(HINSTANCE hInst, int CmdShow,
LRESULT (WINAPI *pWndProc) (HWND,UINT,WPARAM,LPARAM))
{
WNDCLASSEX wc;
wc.cbSize = sizeof(wc);
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.lpfnWndProc = pWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) ::GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"WndClass";
wc.hIconSm = ::LoadIcon(NULL, IDI_APPLICATION);
::RegisterClassEx(&wc);
HWND hWnd = ::CreateWindow(L"WndClass", L"",
WS_OVERLAPPEDWINDOW,
100, 100,
500, 500,
NULL, (HMENU) NULL, hInst, NULL);
::ShowWindow(hWnd, CmdShow);
return hWnd;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmLine, int nCmdShow)
{
HWND parent = CreateMainWindow(hInstance, nCmdShow, WndProc);
RichEdit re(parent);
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
return msg.wParam;
}
Text:
യൗവനം നശിക്കാത്തവനു മാത്രമേ സുന്ദരികളുടേയും സുന്ദരന്മാരുടേയും കഥ പറയാനാകൂ. പി.സി കുട്ടികൃഷ്ണന്‍ ആ ഗണത്തില്‍പ്പെടും. അതുകൊണ്ടാവും അദ്ദേഹം യൗവനം നശിക്കാത്തവന്‍ എന്നര്‍ത്ഥം വരുന്ന ഉറൂബ് എന്ന പേര് തൂലികാനാമമായി സ്വീകരിച്ചത്.
'സുന്ദരികളും സുന്ദരന്മാരും'-ഇതിഹാസസമൃദ്ധിയുള്ള ആ ഒറ്റ നോവല്‍ മതിയല്ലോ ഉറൂബിനെ മലയാളി നിത്യവും ഓര്‍മ്മിക്കാന്‍. 1920-കളിലെ ഖിലാഫത്ത് പ്രസ്ഥാനം, ദേശീയ സ്വാതന്ത്ര്യ സമരം, മലബാര്‍ കലാപം, കമ്മ്യൂണിസ്റ്റ് മുന്നേറ്റം, രണ്ടാം ലോകമഹായുദ്ധം തുടങ്ങിയവയുടെ പശ്ചാത്തലത്തില്‍ മലബാര്‍ കേന്ദ്രമാക്കി നിരവധി വ്യക്തികളുടെ ജീവിതങ്ങളിലൂടെ രാഷ്ട്രീയ-സാമൂഹിക-കുടുംബ ബന്ധങ്ങളില്‍വന്ന വമ്പിച്ച മാറ്റങ്ങള്‍ അവതരിപ്പിക്കുന്ന നോവലാണ് 'സുന്ദരികളും സുന്ദരന്മാരും'. ഉമ്മാച്ചു, അണിയറ, മിണ്ടാപ്പെണ്ണ്, അമ്മിണി, ആമിന, തേന്മുള്ളുകള്‍ എന്നീ നോവലുകളും 'രാച്ചിയമ്മ'യും 'ഗോപാലന്‍നായരുടെ താടി'യും പോലുള്ള സുന്ദരങ്ങളായ നിരവധി ചെറുകഥകളും ഉറൂബ് മലയാളത്തിനു നല്കി. നാടകം, കവിത, ഉപന്യാസം എന്നീ മേഖലകളിലും ഉറൂബിന്റെ സംഭാവനകളുണ്ട്.
Any ideas what it can be?

creating rebar control and introduction a band with toolbar into the rebar

I use this code to create a rebar control, and introduction a band with toolbar into the rebar.
But when window is shown up, I can not see the toolbar. and when I check the height of the rebar, in this line of code: int height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; I find rebar's height is only 4 pixels.
#include <windows.h>
#include <stdlib.h>
#include <CommCtrl.h>
#pragma comment(lib, "comctl32.lib")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE instance;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
instance = hInstance;
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"Example";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
RegisterClassEx(&wcex);
HWND hWnd = CreateWindow(L"Example", L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
500, 500, NULL, NULL, hInstance, NULL);
// Initialize common controls.
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
InitCommonControlsEx(&icex);
HWND hwndRebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
0, 0, 100, 50, hWnd, NULL, instance, NULL);
// create toolbar
HWND hWndToolbar = CreateWindowEx(0 , TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_TOOLTIPS,
0, 0, 0, 0, hwndRebar, (HMENU)0, instance, NULL);
HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR16 | ILC_MASK, 3, 0);
SendMessage(hWndToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hImageList);
SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
TBBUTTON tbb[4] =
{
{0,0,TBSTATE_ENABLED,TBSTYLE_BUTTON},
{1,1,TBSTATE_ENABLED,TBSTYLE_BUTTON},
{2,2,TBSTATE_ENABLED,TBSTYLE_BUTTON},
};
SendMessage(hWndToolbar, (UINT) TB_ADDBUTTONS, 3, (LPARAM)&tbb);
SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
ShowWindow(hWndToolbar , SW_SHOW);
// Initialize band info.
REBARBANDINFO rbBand = { sizeof(REBARBANDINFO) };
rbBand.fMask = RBBIM_STYLE | RBBIM_TEXT | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_COLORS;
rbBand.fStyle = RBBS_GRIPPERALWAYS;
// Get the height of the toolbar.
DWORD dwBtnSize = (DWORD)SendMessage(hWndToolbar, TB_GETBUTTONSIZE, 0,0);
// Set values unique to the band with the toolbar.
rbBand.clrFore = RGB(233, 233, 233);
rbBand.clrBack = RGB(200, 200, 200);
rbBand.lpText = TEXT("");
rbBand.hwndChild = hWndToolbar;
rbBand.cyChild = LOWORD(dwBtnSize);
rbBand.cyMinChild = LOWORD(dwBtnSize);
rbBand.cxMinChild = 3 * HIWORD(dwBtnSize);
// The default width is the width of the buttons.
rbBand.cx = 0;
// Add the band
SendMessage(hwndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
// show the main window
ShowWindow(hWnd, nCmdShow);
// check the rebar size
WINDOWPLACEMENT wp;
GetWindowPlacement(hwndRebar, &wp);
int height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
As follows from the comments, the solution was:
REBARBANDINFO rbBand;
rbBand.cbSize = REBARBANDINFO_V3_SIZE;
// initialize the rest here
This seems to affect older versions of Windows (specifically, XP), because the original code compiles and runs fine on Windows 7.
This was mentioned in the comments to a MSDN page: http://msdn.microsoft.com/en-us/library/windows/desktop/bb774393.aspx
As was already stated, the cbSize member of the REBARBANDINFO struct needed to be set.
Note the following about the provided code as well:
The images on the toolbar buttons don't show up. Right after creating the image list you have to make the following call to load the images:
SendMessage(hWndToolbar, TB_LOADIMAGES, (WPARAM)IDB_STD_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
The TBBUTTON array is declared with a size of 4 but it only gets populated with 3 items. Technically it should be declared as:
TBBUTTON tbb[3]

Resources