Child window does not get created - c++

EDIT : Now this is strange, if I move the call to jItems::populate ( std::string myList ) to the constructor of jDropDown::jDropDown from else where in the jDropDown::jDropDown, the child windows get created.
Originally its been called when the dropdown(jDropDown) window is made visible(shown), and the flow of the program doesn't allow a call to jItems::populate ( std::string myList ) be moved to constructor of jDropDown::jDropDown.
What I an trying to do is create a custom Dropdown box from scratch, the problem I am facing is the final Items(jItem) windows are not created, its an oop design and
every Items(jItem) is derived from jPanel, the other parts of the dropdown box are also drived from jPanel so creating each and every window follows the same process yet the final
Items(jItem) windows are not created, they are not visible and I can't find them with visual studio Spy++
I have checked for instance handle and window handle, and both the checks returns true, yet the jItem windows are not visible and can't find them in spy++ (I can see all the other windows in spy++)
Any help is appreciated.
Here is a reference image and some relevant code.
bool jPanel::registered = false;
jPanel::jPanel( std::string txt, int x, int y, int width, int height, HWND parent, HINSTANCE hInstance, WORD bitmap, DWORD style )
: jControl( parent, hInstance, bitmap )
{
if ( ! registered )
{
WNDCLASSEX wincl;
wincl.hInstance = hInstance;
wincl.lpszClassName = "jPanel";
wincl.lpfnWndProc = WndProc;
wincl.style = CS_BYTEALIGNWINDOW;
wincl.cbSize = sizeof ( WNDCLASSEX );
wincl.hIcon = 0;
wincl.hIconSm = 0;
wincl.hCursor = ::LoadCursor ( NULL, IDC_ARROW );
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 4;
wincl.hbrBackground = ::CreateSolidBrush ( backgroundColor );
::RegisterClassEx ( &wincl );
jPanel::registered = true;
}
DWORD flag = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD;
if ( style ) flag = flag | style;
hwnd = ::CreateWindowEx ( 0, "jPanel", txt.c_str ( ), flag, x, y, width, height, parent, 0, hInstance, ( LPVOID ) this ) ;
};
jDropDown::jDropDown ( std::string txt, int x, int y, int width, int height, HWND parent, HINSTANCE hInstance, WORD bitmap )
: jPanel ( txt, x, y, width, height, parent, hInstance, bitmap ), capture ( false ), populated ( false )
{
RECT rect;
::GetWindowRect ( hwnd, &rect );
::MapWindowPoints ( HWND_DESKTOP, ::GetParent ( parent ), ( LPPOINT ) &rect, 2 );
items = new jItems ( "My Items List", rect.left, rect.top + height, width, 300, ::GetParent( parent ), hInstance, 0 );
items->setBackgroundColor ( RGB ( 100, 100, 100 ) );
};
jItems::jItems ( std::string txt, int x, int y, int width, int height, HWND parent, HINSTANCE hInstance, WORD bitmap )
: jPanel ( txt, x, y, width, height, parent, hInstance, bitmap ), wWidth ( width ), wHeight ( 30 )
{
::SetWindowPos ( this->hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
};
bool jItems::populate ( std::string myList )
{
int y = 0;
Hinstance hInstance = ::GetModuleHandle ( NULL );
std::vector < std::string > list = model::Service::explode ( "^", myList );
for ( std::vector < std::string >::const_iterator it = list.begin ( ); it != list.end ( ); ++it )
{
std::string s = *it;
jItem *i = new jItem ( "Your Item", 0, y, wWidth, wHeight, this->hwnd, hInstance, 0 );
}
::SetWindowPos ( this->hwnd, HWND_TOP, 0, 0, wWidth, list.size ( ) * wHeight, SWP_NOMOVE | SWP_NOZORDER );
return true;
};
jItem::jItem ( std::string txt, int x, int y, int width, int height, HWND parent, HINSTANCE hInstance, WORD bitmap )
: jPanel ( txt, x, y, width, height, parent, hInstance, bitmap ), empty ( false )
{
this->setBackgroundColor ( RGB ( 65, 65, 65 ) );
};

Related

OpenGL + Visual Studio 2017 : rendering window not displayed (was OK with Visual 2010)

Updated:
The problem is solved! the solution is inspired by an advice in comments:
I just updated the graphic driver and now all my code works fine.
For information, the mentioned driver is "Inter(R) UHD Graphics 620" that I updated to the version 25.20.10.6472 (10/12/2018).
Very sorry for the inconvenience, and thank you for all your support.
Using ScreenToGif (thanks to Strive Sun) here is what it looks like : the main (OpenGL) window is an external view of some kind of space ship (with colorful boosters), and at the bottom right the (GDI) window is the view from the AI pilote which is learning to eat green gums and avoid red ones).
If you, Mr StackOverflow, think this kind of rambling is not appropriate, please remove it...
Below, the original question:
I have a small sample of OpenGl code under windows that works fine with windows 7 + visual studio 2010.
But on my new PC with windows 10 + visual studio 2017, the OpenGL rendering window is not displayed.
Compilation is ok and no error is returned during execution.
So, in order to post it here without bothering you with tons of stuff, I wrote a short extract of my code.
It uses only basic native gdi+opengl functions provided by the standard win API (gl.h/glu.h), but not any additional library (as glew/glut/freeglut/...).
With Windows7+VS2010 I have 3 windows: a GDI rendering, an OpenGL rendering and a console.
On the first: some crossing blue lines (using "LineTo").
On the second: one violet triangle (using "glVertex3d").
On the console a message telling me that all functions well returned.
With Windows10+VS2017, the OpenGL window is not visible.
I don't even see a ghost when I play with alt-tab keys.
I suppose that something has changed in the API, but I can't figure out what...
So here is my code :
#include <windows.h>
#include <cstdio>
#include <GL/GLU.h>
static LRESULT CALLBACK win32callback ( HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam )
{
return DefWindowProcA( hWnd,message,wParam,lParam ) ;
}
HWND create_window ( BOOL & ok , int x )
{
WNDCLASSEXA wcx ;
memset( &wcx,0,sizeof( wcx )) ;
wcx.cbSize = sizeof( wcx ) ;
wcx.lpfnWndProc = win32callback ;
wcx.lpszClassName = "spam" ;
RegisterClassExA( &wcx ) ;
HWND hwnd = CreateWindowExA( 0,"spam",NULL,WS_POPUP,x+10,10,500,500,NULL,NULL,NULL,NULL ) ;
ok = ok && SetWindowPos( hwnd,HWND_TOPMOST,x+10,10,500,500,SWP_NOOWNERZORDER|SWP_SHOWWINDOW ) ;
ok = ok && ShowWindow( hwnd,SW_SHOWNORMAL ) ;
return hwnd ;
}
void play_opengl ( HWND hwnd , BOOL & ok )
{
HDC dc = GetWindowDC( hwnd ) ;
PIXELFORMATDESCRIPTOR pfd ;
memset( &pfd,0,sizeof( PIXELFORMATDESCRIPTOR )) ;
pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR ) ;
pfd.nVersion = 1 ;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER ;
pfd.iPixelType = PFD_TYPE_RGBA ;
pfd.cColorBits = 24 ;
pfd.cDepthBits = 32 ;
pfd.iLayerType = PFD_MAIN_PLANE ;
int PixFormat = ChoosePixelFormat( dc,&pfd ) ;
ok = ok && SetPixelFormat( dc,PixFormat,&pfd ) ;
HGLRC glrc = wglCreateContext( dc ) ;
ok = ok && wglMakeCurrent( dc,glrc ) ;
glViewport( 0,0,500,500 ) ;
glEnable( GL_COLOR_MATERIAL ) ;
glMatrixMode( GL_PROJECTION ) ;
gluPerspective( 70,1,0.1,1000 ) ;
glMatrixMode( GL_MODELVIEW ) ;
glLoadIdentity() ;
glColor3b( 100,50,120 ) ;
glTranslated( 0,0,-20 ) ;
glBegin( GL_TRIANGLES ) ;
glVertex3d( 0,0,0 ) ;
glVertex3d( 5,5,0 ) ;
glVertex3d( 0,5,0 ) ;
glEnd() ;
ok = ok && SwapBuffers( dc ) ;
}
void play_gdi ( HWND hwnd , BOOL & ok )
{
HDC windc = GetWindowDC( hwnd ) ;
HDC dc = CreateCompatibleDC( windc ) ;
HBITMAP bitmap = CreateCompatibleBitmap( windc,500,500 ) ;
HPEN pen = CreatePen( PS_SOLID,1,0xffaa55 ) ;
ok = ok && (SelectObject( dc,bitmap ) != NULL) ;
ok = ok && (SelectObject( dc,pen ) != NULL) ;
for ( int i = 0 ; i < 100 ; i++ )
ok = ok && LineTo( dc,(i&1?i:100-i)*4,(i&1)*400 ) ;
BitBlt( windc,0,0,500,500,dc,0,0,SRCCOPY ) ;
}
void main ()
{
BOOL ok = TRUE ;
HWND hwnd1 = create_window( ok,0 ) ;
HWND hwnd2 = create_window( ok,600 ) ;
play_gdi( hwnd1,ok ) ;
play_opengl( hwnd2,ok ) ;
// sorry I don't clean up anything...
if (ok) printf("\n all correct!\n") ;
printf("\n\n press ENTER") ;
getchar() ;
}
What you're talking about is that ghost window are created by the following code.
for ( int z = -n ; z <= n ; z++ )
for ( int y = -n ; y <= n ; y++ )
for ( int x = -n ; x <= n ; x++ )
{
printf(" %d,%d,%d%s",x,y,z,x?"":"\n") ;
SwapBuffers( dc ) ;
glTranslated( x,y,z ) ;
gluSphere( quadric,4,5,5 ) ;
glTranslated( -x,-y,-z ) ;
}
I don't know what window you want to render with this code, but that's the case. Your for loop has been looping around the sphere matrix.
I'm trying to replace some of your code with mine for testing purposes.
#include <windows.h>
#include <cstdio>
#include <math.h>
#include <GL/GLU.h>
#pragma comment (lib,"Glu32.lib")
#pragma comment (lib,"Opengl32.lib")
void draw();
int width, height; // the desired width and height of the CLIENT AREA
HDC dc;
static LRESULT CALLBACK win32callback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
void main()
{
WNDCLASSEXA wcx;
memset(&wcx, 0, sizeof(wcx));
wcx.cbSize = sizeof(wcx);
wcx.lpfnWndProc = win32callback;
wcx.lpszClassName = "spam";
RegisterClassExA(&wcx);
HWND hwnd = CreateWindowExA(0, "spam", NULL, WS_POPUP, 10, 10, 500, 500, NULL, NULL, NULL, NULL);
SetWindowPos(hwnd, HWND_TOPMOST, 10, 10, 800, 500, SWP_NOOWNERZORDER | SWP_SHOWWINDOW);
ShowWindow(hwnd, TRUE);
SetFocus(hwnd);
dc = GetWindowDC(hwnd);
RECT rect;
SetRect(&rect, 50, // left
50, // top
850, // right
650); // bottom
// Save width and height off.
width = rect.right - rect.left;
height = rect.bottom - rect.top;
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 24;
int PixFormat = ChoosePixelFormat(dc, &pfd);
PIXELFORMATDESCRIPTOR bestMatch_pfd;
DescribePixelFormat(dc, PixFormat, sizeof(pfd), &bestMatch_pfd);
SetPixelFormat(dc, PixFormat, &pfd);
HGLRC glrc = wglCreateContext(dc);
wglMakeCurrent(dc, glrc);
while (1)
{
draw();
}
DestroyWindow(hwnd);
wglMakeCurrent(0, 0);
wglDeleteContext(glrc);
}
void draw()
{
// 1. set up the viewport
glViewport(0, 0, g.width, g.height); // set viewport
// 2. projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (float)g.width / (float)g.height, 1, 1000);
// 3. viewing transformation
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 10,
0, 0, 0,
0, 1, 0);
// 4. modelling transformation and drawing
glClearColor(0.5, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
static float i = 0.01f;
i += 0.001f; // increase i by 0.001 from its
// it had on the LAST FUNCTION CALL to the draw() function
float c = cos(i);
float s = sin(i);
glBegin(GL_TRIANGLES);
glColor3f(c, 0, 0); // red
glVertex3f(1 + c, 0 + s, 0);
glColor3f(c, s, 0); // yellow
glVertex3f(0 + c, 1 + s, 0);
glColor3f(s, 0.1f, s); // magenta
glVertex3f(-1 + c, 0 + s, 0);
glEnd();
//7. SWAP BUFFERS.
SwapBuffers(dc);
}
You can see that it works very well, my environment configuration:VS2017 Window 10
Updated:
Try linking "Glu32.lib" and "Opengl32.lib"
Updated:
Try the following two methods:
The graphics card does not support the current OpenGL version, download EVEREST Ultimate Edition, click on the display device > OpenGL in turn after installation and operation to check whether it supports the relevant information, if not, you can only replace the graphics card or replace it with the supported OpenGL version to solve the problem.
The graphics card driver is not supported. Updating the graphics card driver is enough.

Using DeferWindowPos to update z order?

I'm trying to use DeferWindowPos to update the z order of some dialog boxes, but it's not working. Well, the z order does change, but not always in the requested order. Why could that be? It's supposed to work, right?
I am checking all the return values. I observered that if I add the flag SWP_NOSENDCHANGING, DeferWindowPos returns 0 without GetLastError() returning any error code. I didn't add message handlers for WM_WINDOWPOSCHANGING in any of my dialog classes.
For now I use SetWindowPos instead. It always works but it's slower.
I wrote a test, see code below. Any help would be much appreciated.
void test()
{
#ifdef DEFER_WINDOW_POS
class DeferPos
{
public:
DeferPos( const int innWindowCount = 1 )
{
m_hdwp = BeginDeferWindowPos( innWindowCount );
assert( m_hdwp != nullptr );
}
~DeferPos()
{
if( !EndDeferWindowPos(m_hdwp) ) { assert( false ); }
}
void Set( HWND hWnd, HWND hWndAfter, int x, int y, int nWidth, int nHeight, UINT uFlags )
{
assert( m_hdwp != nullptr );
assert( GetLastError() == 0 );
m_hdwp = DeferWindowPos( m_hdwp, hWnd, hWndAfter, x, y, nWidth, nHeight, uFlags );
assert( m_hdwp != nullptr );
assert( GetLastError() == 0 );
}
private:
HDWP m_hdwp = nullptr;
};
auto update_z_order = [](const std::vector<HWND>& vec, UINT flags)
{
DeferPos dp( static_cast<int>(vec.size()) );
HWND hWndAfter = HWND_TOP;
for( HWND hWnd : vec )
{
dp.Set( hWnd, hWndAfter, 0, 0, 0, 0, flags );
hWndAfter = hWnd;
}
};
#else
auto update_z_order = [](const std::vector<HWND>& vec, UINT flags)
{
HWND hWndAfter = HWND_TOP;
for( HWND hWnd : vec )
{
::SetWindowPos(hWnd, hWndAfter, 0, 0, 0, 0, flags );
hWndAfter = hWnd;
}
};
#endif
auto get_dialog_z_order = []()
{
std::vector<HWND> vec;
EnumWindows( [](HWND hWnd, LPARAM lparam)-> BOOL
{
if( dynamic_cast<CDialog*>(CWnd::FromHandle(hWnd)) )
{
reinterpret_cast<std::vector<HWND>*>(lparam)->push_back( hWnd );
}
return TRUE;
}, reinterpret_cast<LPARAM>(&vec) );
return vec;
};
const std::vector<HWND> original_order = get_dialog_z_order();
const std::vector<HWND> reverse_order( original_order.rbegin(), original_order.rend() );
const UINT flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE;
update_z_order( reverse_order, flags );
const std::vector<HWND> new_order = get_dialog_z_order();
assert( new_order == reverse_order ); // this assert sometimes fails when DEFER_WINDOW_POS is defined
}

Win32: UpdateLayeredWindow failing sometimes (error 317)

I have a bizarre issue here. I'm displaying a semi-transparent splash screen (a .png file) using layered windows. It works on some machines but not others. On the machines where it doesn't work, the GetLastError returns 317 (which isn't very helpful). Has anyone experienced this before? Here are my relevant functions. The incoming parameters for CreateAsPNG are WS_VISIBLE|WS_POPUP (dwStyle), 0 (dwExStyle), and the handle to a hidden tool window for the parent so no taskbar entry is created. I've verified that I can load an embedded PNG resource into CImage and that the size of the image is correct.
Thanks in advance for any help!
BOOL MySplashWnd::CreateAsPNG( DWORD dwStyle, DWORD dwExStyle, const CString& sTitle, HWND hWndParent )
{
ATL::CImage img;
CreateStreamOnResource( m_nBitmapID, img );
m_nWndWidth = img.GetWidth();
m_nWndHeight = img.GetHeight();
int nTop = 0;
int nLeft = 0;
GetTopLeft( nTop, nLeft );
dwExStyle |= WS_EX_LAYERED;
// Create the Splash Window
BOOL bRetVal = CWnd::CreateEx( dwExStyle, AfxRegisterWndClass( CS_CLASSDC ), sTitle,
dwStyle, nLeft, nTop, m_nWndWidth, m_nWndHeight, hWndParent, NULL );
//Couldn't create the window for some unknown reason...
X_ASSERT( bRetVal != FALSE );
if ( bRetVal )
{
HDC hScreenDC = ::GetDC( m_hWnd );
HDC hDC = ::CreateCompatibleDC( hScreenDC );
HBITMAP hBmp = ::CreateCompatibleBitmap( hScreenDC, m_nWndWidth, m_nWndHeight );
HBITMAP hBmpOld = ( HBITMAP ) ::SelectObject( hDC, hBmp );
img.Draw( hDC, 0, 0, m_nWndWidth, m_nWndHeight, 0, 0, m_nWndWidth, m_nWndHeight );
BLENDFUNCTION blend = { 0 };
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
POINT ptPos = { nLeft, nTop };
SIZE sizeWnd = { m_nWndWidth, m_nWndHeight };
POINT ptSource = { 0, 0 };
if ( ::UpdateLayeredWindow( m_hWnd, hScreenDC, &ptPos, &sizeWnd, hDC, &ptSource, 0, &blend, ULW_ALPHA ) )
{
}
else
{
// The last error value is 317 on some Win7 machines.
TRACE( _T( "*** Last error: %d\n" ), ::GetLastError() );
}
::SelectObject( hDC, hBmpOld );
::DeleteObject( hBmp );
::DeleteDC( hDC );
::ReleaseDC( NULL, hScreenDC );
}
return bRetVal;
}
void MySplashWnd::CreateStreamOnResource( UINT nIDRes, ATL::CImage& img )
{
HINSTANCE hInstance = ::GetMUIResourceInstance();
if ( hInstance == NULL )
{
return;
}
HRSRC hResource = ::FindResource( hInstance, MAKEINTRESOURCE( nIDRes ), "PNG" );
if ( hResource == NULL )
{
return;
}
DWORD dwResourceSize = ::SizeofResource( hInstance, hResource );
if ( dwResourceSize == 0 )
{
return;
}
HGLOBAL hImage = ::LoadResource( hInstance, hResource );
if ( hImage == NULL )
{
return;
}
LPVOID pvImageResourceData = ::LockResource( hImage );
if ( pvImageResourceData == nullptr )
{
return;
}
HGLOBAL hImageData = ::GlobalAlloc( GMEM_MOVEABLE, dwResourceSize );
if ( hImageData == NULL )
{
return;
}
LPVOID pvImageBuffer = ::GlobalLock( hImageData );
if ( pvImageBuffer != nullptr )
{
::CopyMemory( pvImageBuffer, pvImageResourceData, dwResourceSize );
::GlobalUnlock( hImageData );
IStream* pStream = nullptr;
if ( SUCCEEDED( ::CreateStreamOnHGlobal( hImageData, TRUE, &pStream ) ) )
{
img.Load( pStream );
pStream->Release();
}
::GlobalUnlock( hImageData );
}
::GlobalFree( hImageData );
} // CTTSplashWnd::CreateStreamOnResource
UPDATE: I've found that even on the same machine, sometimes UpdateLayeredWindow succeeds and other time it fails (but always with code 317 if it does fail). Another piece of info is that this splash is being run on a separate UI thread. It always works on my machine though...
I'm having this same problem and I can't find any info either on it. Using SetWindowAttributes method instead works, but I want to use the SetLayeredWindow way. I'm coming to the point where I'm going to debug through the whole windows API to find out what is happening since msdn gives jack info about this error message. The only difference is that the OpenGL layered window demo example I saw which uses this method, uses CreateDIBSection instead of CreateCompatibleBitmap which seems to work on my PC.
I've had UpdateLayeredWindow() work perfectly on a Windows 7 x86_64 machine only for it to start failing when i've disabled desktop composition. It turned out that
UpdateLayeredWindow (window_handle, NULL,
&position, &size,
buffer_hdc, &buffer_offset,
0, &blend_options, ULW_ALPHA);
works, while
UpdateLayeredWindow (window_handle, NULL,
&position, NULL,
buffer_hdc, &buffer_offset,
0, &blend_options, ULW_ALPHA);
does not work and fails with error 317.
I've been trying to skip some of the arguments because i didn't need to change window size or contents, just to move it. With desktop composition disabled, this turned out to be impossible.
Not sure how this relates to your original problem, as you're also supplying the screen DC, while i don't.

Undefined reference to vtable (out of ideas)

I have gone through all I could find on net but seems like I am missing some very basic thing, having spent so much time on this problem isn't making things easier, so I will go ahead and ask for a help here, see if you can find what I am doing wrong.
Here is the code :
jControl.h
#ifndef _JCONTROL_H
#define _JCONTROL_H
namespace view
{
class jControl
{
public:
HWND hwnd;
HWND hParent;
HBITMAP hbitmap;
std::string text;
HFONT hFont;
COLORREF textColor;
COLORREF backgroundColor;
RECT updateRegion;
bool isUpdateRegion;
public:
jControl ( );
jControl ( HWND parent, HINSTANCE hInstance, WORD bitmap );
~jControl ( );
virtual void show ( );
virtual void hide ( );
virtual void disable ( );
virtual void enable ( );
virtual std::string getText ( );
virtual void setText ( std::string txt );
virtual void setUpdateRegion ( RECT rect );
virtual void setTextColor ( COLORREF crf );
virtual void setBackgroundColor ( COLORREF crf );
virtual void setFont ( HFONT font );
virtual bool setRange ( int range );
virtual bool setStep ( int step );
};
};
#endif
jControl.cpp
#include "jControl.h"
namespace view
{
jControl::jControl( ){};
jControl::jControl ( HWND parent, HINSTANCE hInstance, WORD bitmap )
: hParent ( parent ), hbitmap ( NULL ), isUpdateRegion ( false ), textColor ( RGB ( 255, 255, 255 ) ), backgroundColor ( RGB ( 54, 54, 54 ) )
{
hFont = ::CreateFont ( 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Myriad Pro" );
if ( bitmap != 0 ) hbitmap = LoadBitmap ( hInstance, MAKEINTRESOURCE ( bitmap ) );
};
jControl::~jControl ( )
{
if ( hbitmap ) DeleteObject ( hbitmap );
if ( hFont ) DeleteObject ( hFont );
if ( hwnd ) DestroyWindow ( hwnd );
};
void jControl::show( ) { ::ShowWindow( hwnd, SW_SHOW ); };
void jControl::hide( ) { ::ShowWindow( hwnd, SW_HIDE ); };
void jControl::disable ( ) { EnableWindow ( hwnd, false ); };
void jControl::enable ( ) { EnableWindow ( hwnd, true ); };
std::string jControl::getText ( ) { return text; };
void jControl::setText ( std::string txt ) { text = txt; InvalidateRect ( hwnd, NULL, true ); };
void jControl::setUpdateRegion ( RECT rect ) { updateRegion = rect; isUpdateRegion = true; };
void jControl::setTextColor ( COLORREF crf ) { textColor = crf; };
void jControl::setBackgroundColor ( COLORREF crf ) { backgroundColor = crf; ::InvalidateRect ( hwnd, NULL, true ); };
void jControl::setFont ( HFONT font ) { hFont = font; };
bool jControl::setRange ( int range ) { return true; };
bool jControl::setStep ( int step ) { return true; };
};
jProgressBar.h
#ifndef _JPROGRESSBAR_H
#define _JPROGRESSBAR_H
/** * Parent class include */
#ifndef _JCONTROL_H
#include "../jControl/jControl.h"
#endif
namespace view
{
class jProgressBar : public jControl
{
public:
jProgressBar ( std::string txt, int x, int y, int width, int height, HWND parent, HINSTANCE hInstance, WORD bitmap );
~jProgressBar ( );
std::string getText ( );
void setText ( std::string txt );
bool setRange ( int range );
bool setStep ( int step );
};
};
#endif
jProgressBar.cpp
#include "jProgressBar.h"
namespace view
{
jProgressBar::jProgressBar( std::string txt, int x, int y, int width, int height, HWND parent, HINSTANCE hInstance, WORD bitmap )
: jControl( parent, hInstance, bitmap )
{
hwnd = CreateWindowEx ( WS_EX_TOPMOST, PROGRESS_CLASS, txt.c_str(), WS_CHILD | WS_CLIPSIBLINGS | WS_CHILD, x, y, width, height, parent, 0, hInstance, 0 );
};
jProgressBar::~jProgressBar ( ){};
bool jProgressBar::setRange ( int range )
{
if ( SendMessage ( hwnd, PBM_SETRANGE, 0, MAKELPARAM ( 0, range ) ) != 0 ) return true;
return false;
};
bool jProgressBar::setStep ( int step )
{
if ( SendMessage ( hwnd, PBM_SETSTEP, ( WPARAM ) step, 0 ) != 0 ) return true;
return false;
};
};
And here is the error :
[Linker error] jProgressBar/jProgressBar.cpp:14: undefined reference to `vtable for view::jProgressBar'
I get the error on Constructor and Destructor of JProgressBar.
The problem may be in these lines:
std::string getText( );
and
void setText( std::string txt );
in jProgressBar.h
Please provide a definition for this function in Cpp or remove it from header, I think it should compile. The main reason is: you have overridden a virtual function in a child class with a declaration, but haven't given a definition for the method.
The compiler knows about the function, but the linker is not able to find the definition
For example:
class Base
{
virtual void f() = 0;
}
class Derived : public Base
{
void f();
}

Listbox change width dynamically

Listboxes do not auto-resize. The best we've got is:
SendMessage(my_listbox, LB_SETHORIZONTALEXTENT, 1000, 0);
MS helpfully notes that "...a list box does not update its horizontal extent dynamically."
(why the heck not...but I digress)
How can the width be set dynamically to avoid truncating the text of a message longer than 1000px?
if I understand the question... :-)
You'll essentially need to measure all of the items in the list box and calculate the maximum width of the list box contents, and then adjust the width of the listbox.
Here's some code from this project (that adds a automatic horizontal scrollbar to listboxes). This snippet is called when the font changes but it demonstrates (roughly) what's needed:
static void OnSetFont( HWND hwnd, HFONT hFont )
//
// Font has changed!
// We need to measure all of our items and reset the horizontal extent of the listbox
{
CData *pData = reinterpret_cast< CData * >( ::GetProp( hwnd, g_pcszDataProperty ) );
pData->m_hFont = hFont;
//
// Set up a HDC...
HDC hdc = GetDC( hwnd );
HGDIOBJ hOld = SelectObject( hdc, pData->m_hFont );
//
// Record the average width for use as our 'fudge factor' later.
TEXTMETRIC tm;
GetTextMetrics( hdc, &tm );
pData->m_nAvergeCharWidth = tm.tmAveCharWidth;
pData->m_nMaxWidth = 0;
//
// This is used as our item buffer. Saves us from having to handle the reallocation
// for different string lengths
CArray< TCHAR, TCHAR > arrBuffer;
//
// Quick reference to make the code below read better
CArray< int, int > &arrWidth = pData->m_arrItemWidth;
//
// The main loop. Iterate over the items, get their text from the listbox and measure
// it using our friendly little helper function.
const UINT uCount = arrWidth.GetSize();
for( UINT u = 0; u < uCount; u++ )
{
const int nLength = ::SendMessage( hwnd, LB_GETTEXTLEN, u, 0 );
arrBuffer.SetSize( nLength + 1 );
::SendMessage( hwnd, LB_GETTEXT, u, (WPARAM)arrBuffer.GetData() );
const int nItemWidth = BaseMeasureItem( pData, hwnd, hdc, arrBuffer.GetData() );
pData->m_arrItemWidth.SetAt( u, nItemWidth );
if( nItemWidth > pData->m_nMaxWidth )
{
pData->m_nMaxWidth = nItemWidth;
}
}
//
// Now, either set the horizontal extent or not, depending on whether we think we need it.
if( pData->m_nMaxWidth > pData->m_nClientWidth )
{
::SendMessage( hwnd, LB_SETHORIZONTALEXTENT, pData->m_nMaxWidth + pData->m_nAvergeCharWidth, 0 );
}
else
{
::SendMessage( hwnd, LB_SETHORIZONTALEXTENT, 0, 0 );
}
//
// The usual release of resources.
SelectObject( hdc, hOld );
ReleaseDC( hwnd, hdc );
}
and...
static int BaseMeasureItem( CData *pData, HWND hwnd, HDC hdc, LPCTSTR pcszText )
//
// Measure and item and adjust the horizontal extent accordingly.
// Because the HDC is already set up we can just do it.
// We return the width of the string so our caller can use it.
{
SIZE size;
::GetTextExtentPoint32( hdc, pcszText, _tcslen( pcszText ), &size );
if( size.cx > pData->m_nMaxWidth )
{
pData->m_nMaxWidth = size.cx;
if( pData->m_nMaxWidth > pData->m_nClientWidth )
{
::SendMessage( hwnd, LB_SETHORIZONTALEXTENT, pData->m_nMaxWidth + pData->m_nAvergeCharWidth, 0 );
}
}
return size.cx;
}