How to Create a drop down button in Windows Vista, 7?

 

MenuIn this post, I’m introducing the new button style which is introduced in Windows Vista and above. It’s no more painful to create a Drop down button with Windows Vista, earlier it was accomplished by placing two controls side by side and handle it’s message separately.

Windows Vista introduced new button style BS_SPLITBUTTON and you can set this new style by specifying as parameter of CreateWindow API if you’re dynamically creating button control or by modifying the style using ModifyStyle API. To use this style Windows Vista or higher required .


Using with CreateWindow/CButton::Create API

[sourcecode language='cpp']
HWND hWndButtonMain = CreateWindow(_T(“Button”), _T(“Split Button”),
WS_CHILD | WS_VISIBLE | BS_SPLITBUTTON,
10, 10, 120, 50,
m_hWnd, (HMENU)IDC_BTN_BUTTON1, AfxGetApp()->m_hInstance, NULL);
[/sourcecode]

Or

[sourcecode language='cpp']
CButton* pButton = new CButton;
pButton->Create( _T( “Split Button”), WS_CHILD | WS_VISIBLE | BS_SPLITBUTTON,CRect(10,10,120,50),this,IDC_BUTTON1);
[/sourcecode]

Or modifying Existing control

[sourcecode language='cpp']
m_SplitButton.ModifyStyle(0, BS_SPLITBUTTON );
[/sourcecode]

Handling Dropdown Event

Add message handler for BCN_DROPDOWN in your message handler or in message map of your MFC window class

[sourcecode language='cpp']
ON_NOTIFY(BCN_DROPDOWN, IDC_BUTTON1, &CControlSampleDlg::OnBnDropDownButton1)
[/sourcecode]

In the message Handler, Display the popup menu and the menu item can be handled using ON_COMMAND message with associated menu ID.

[sourcecode language='cpp']
void CControlSampleDlg::OnBnDropDownButton1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMBCDROPDOWN pDropDown = reinterpret_cast(pNMHDR);

Button_SetDropDownState( m_SplitButton, TRUE );

RECT rc;

// Get the bounding rectangle of the client area
::GetWindowRect(m_SplitButton, &rc);

HMENU hmenu = LoadMenu(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDR_MENU1));
HMENU hmenuTrackPopup;

hmenuTrackPopup = GetSubMenu(hmenu, 0);
TrackPopupMenuEx(hmenuTrackPopup, TPM_RIGHTBUTTON, rc.left, rc.bottom, m_hWnd, NULL);
DestroyMenu(hmenu);

Button_SetDropDownState( m_SplitButton, FALSE );
*pResult = 0;
}
[/sourcecode]

 

How to draw a smooth line using OpenGL?

 

I’d like to share a simple tip on enabling anti aliased line drawing in OpenGL. I hope you’ve basic understanding of OpenGL and how to use it.

To smooth a line, you will have to enable 3 OpenGL capabilities.

  1. Enable line smooth option (GL_LINE_SMOOTH)
  2. Enable Blending( GL_BLEND)
  3. Specify pixel arithmetic(GL_SRC_ALPHA)

Draw the lines after enabling the above properties. See the sample below.

[sourcecode language='cpp']
// Function to enable smoothing
void EnableSmoothing( bool bEnable )
{
if( bEnable )
{
// Smooth out lines
glEnable( GL_LINE_SMOOTH );
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
// Enable Blending
glEnable(GL_BLEND);
// Specifies pixel arithmetic
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
printf( “\nEnabled” );
}
else // if the options are disabled
{
glDisable(GL_LINE_SMOOTH); // Smooth out lines
glDisable(GL_BLEND);
printf( “\nDisabled” );
}
}

// Render function
void RenderScene()
{
glClear( GL_COLOR_BUFFER_BIT );

glRotatef( z, 0, 0, 1 );

/* Draw line for testing */
glBegin( GL_LINES );
{
glColor3f( 0.0f, 0.0f, 1.0f );
glVertex2f( -0.75f, 0.25f );
glColor3f( 0.0f, 1.0f, 0.0f );
glVertex2f( 0.75f,-0.25f );
}
glEnd();

glutSwapBuffers();
}
[/sourcecode]

Line Smooth Sample (3) Line Smooth Sample (4)

See the images before and after conversion. Click on the image to see it in original size.

I’m also attaching a working sample source written using GLUT.

[sourcecode language='cpp']
// LineSmoothSample.cpp : How to smooth line using OpenGL

#include “stdafx.h”
#include
#include

// z rotation angle
GLfloat z = 0.0f;

// Function to enable smoothing
void EnableSmoothing( bool bEnable )
{
if( bEnable )
{
// Smooth out lines
glEnable( GL_LINE_SMOOTH );
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
// Enable Blending
glEnable(GL_BLEND);
// Specifies pixel arithmetic
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
printf( “\nEnabled” );
}
else // if the options are disabled
{
glDisable(GL_LINE_SMOOTH); // Smooth out lines
glDisable(GL_BLEND);
printf( “\nDisabled” );
}
}

// Render function
void RenderScene()
{
glClear( GL_COLOR_BUFFER_BIT );

glRotatef( z, 0, 0, 1 );

/* Draw line for testing */
glBegin( GL_LINES );
{
glColor3f( 0.0f, 0.0f, 1.0f );
glVertex2f( -0.75f, 0.25f );
glColor3f( 0.0f, 1.0f, 0.0f );
glVertex2f( 0.75f,-0.25f );
}
glEnd();

glutSwapBuffers();
}

// Initial setup for rendering context
void SetupRC()
{
glOrtho( -1,1,-1,1,-1,1);
glClearColor( 0,0,0,1);
glLineWidth( 5 );
// Enable smoothing by default
EnableSmoothing( true );
}

// Function to handle change in window size
void ChangeSize( GLsizei w, GLsizei h )
{
glViewport(0,0,w,h);
}

// Keyboard callback
void SpecialKey(unsigned char key, int x, int y)
{
if( ‘ ‘ == key )
{
static bool bEnable = true;
bEnable = !bEnable;
EnableSmoothing( bEnable );
}
else if( ‘w’ == key )
{
z += 0.01f;
if( z >= 360.0f )
z = 0;
}
else
return;

glutPostRedisplay();

}

int main(int argc, char* argv[])
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 800,600 );
glutCreateWindow( “Line Smooth Sample”);
glutReshapeFunc( ChangeSize );
glutDisplayFunc( RenderScene);
glutKeyboardFunc( SpecialKey );
SetupRC();
glutMainLoop();
return 0;
}
[/sourcecode]