271 lines
7.6 KiB
C++
271 lines
7.6 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/msw/checkbox.cpp
|
|
// Purpose: wxCheckBox
|
|
// Author: Julian Smart
|
|
// Modified by:
|
|
// Created: 04/01/98
|
|
// Copyright: (c) Julian Smart
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_CHECKBOX
|
|
|
|
#include "wx/checkbox.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/dcclient.h"
|
|
#include "wx/settings.h"
|
|
#endif
|
|
|
|
#include "wx/renderer.h"
|
|
#include "wx/msw/uxtheme.h"
|
|
#include "wx/msw/private/button.h"
|
|
#include "wx/private/window.h"
|
|
#include "wx/msw/missing.h"
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxCheckBox creation
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void wxCheckBox::Init()
|
|
{
|
|
m_state = wxCHK_UNCHECKED;
|
|
}
|
|
|
|
bool wxCheckBox::Create(wxWindow *parent,
|
|
wxWindowID id,
|
|
const wxString& label,
|
|
const wxPoint& pos,
|
|
const wxSize& size, long style,
|
|
const wxValidator& validator,
|
|
const wxString& name)
|
|
{
|
|
Init();
|
|
|
|
WXValidateStyle(&style);
|
|
if ( !CreateControl(parent, id, pos, size, style, validator, name) )
|
|
return false;
|
|
|
|
WXDWORD exstyle;
|
|
WXDWORD msStyle = MSWGetStyle(style, &exstyle);
|
|
|
|
msStyle |= wxMSWButton::GetMultilineStyle(label);
|
|
|
|
return MSWCreateControl(wxT("BUTTON"), msStyle, pos, size, label, exstyle);
|
|
}
|
|
|
|
WXDWORD wxCheckBox::MSWGetStyle(long style, WXDWORD *exstyle) const
|
|
{
|
|
// buttons never have an external border, they draw their own one
|
|
WXDWORD msStyle = wxControl::MSWGetStyle(style, exstyle);
|
|
|
|
if ( style & wxCHK_3STATE )
|
|
msStyle |= BS_3STATE;
|
|
else
|
|
msStyle |= BS_CHECKBOX;
|
|
|
|
if ( style & wxALIGN_RIGHT )
|
|
{
|
|
msStyle |= BS_LEFTTEXT | BS_RIGHT;
|
|
}
|
|
|
|
return msStyle;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxCheckBox geometry
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxSize wxCheckBox::DoGetBestClientSize() const
|
|
{
|
|
static wxPrivate::DpiDependentValue<wxCoord> s_checkSize;
|
|
|
|
if ( s_checkSize.HasChanged(this) )
|
|
{
|
|
wxClientDC dc(const_cast<wxCheckBox*>(this));
|
|
dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
|
|
|
s_checkSize.SetAtNewDPI(dc.GetCharHeight());
|
|
}
|
|
|
|
wxCoord& checkSize = s_checkSize.Get();
|
|
wxString str = wxGetWindowText(GetHWND());
|
|
|
|
int wCheckbox, hCheckbox;
|
|
if ( !str.empty() )
|
|
{
|
|
wxClientDC dc(const_cast<wxCheckBox *>(this));
|
|
dc.SetFont(GetFont());
|
|
dc.GetMultiLineTextExtent(GetLabelText(str), &wCheckbox, &hCheckbox);
|
|
wCheckbox += checkSize + GetCharWidth();
|
|
|
|
if ( ::GetWindowLong(GetHwnd(), GWL_STYLE) & BS_MULTILINE )
|
|
{
|
|
// We need to make the checkbox even wider in this case because
|
|
// otherwise it wraps lines automatically and not only on "\n"s as
|
|
// we need and this makes the size computed here wrong resulting in
|
|
// checkbox contents being truncated when it's actually displayed.
|
|
// Without this hack simple checkbox with "Some thing\n and more"
|
|
// label appears on 3 lines, not 2, under Windows 2003 using
|
|
// classic look and feel (although it works fine under Windows 7,
|
|
// with or without themes).
|
|
wCheckbox += checkSize;
|
|
}
|
|
|
|
if ( hCheckbox < checkSize )
|
|
hCheckbox = checkSize;
|
|
}
|
|
else
|
|
{
|
|
wCheckbox = checkSize;
|
|
hCheckbox = checkSize;
|
|
}
|
|
|
|
return wxSize(wCheckbox, hCheckbox);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxCheckBox operations
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void wxCheckBox::SetLabel(const wxString& label)
|
|
{
|
|
wxMSWButton::UpdateMultilineStyle(GetHwnd(), label);
|
|
|
|
wxCheckBoxBase::SetLabel(label);
|
|
}
|
|
|
|
void wxCheckBox::SetValue(bool val)
|
|
{
|
|
Set3StateValue(val ? wxCHK_CHECKED : wxCHK_UNCHECKED);
|
|
}
|
|
|
|
bool wxCheckBox::GetValue() const
|
|
{
|
|
return Get3StateValue() != wxCHK_UNCHECKED;
|
|
}
|
|
|
|
void wxCheckBox::Command(wxCommandEvent& event)
|
|
{
|
|
int state = event.GetInt();
|
|
wxCHECK_RET( (state == wxCHK_UNCHECKED) || (state == wxCHK_CHECKED)
|
|
|| (state == wxCHK_UNDETERMINED),
|
|
wxT("event.GetInt() returned an invalid checkbox state") );
|
|
|
|
Set3StateValue((wxCheckBoxState) state);
|
|
ProcessCommand(event);
|
|
}
|
|
|
|
wxCOMPILE_TIME_ASSERT(wxCHK_UNCHECKED == BST_UNCHECKED
|
|
&& wxCHK_CHECKED == BST_CHECKED
|
|
&& wxCHK_UNDETERMINED == BST_INDETERMINATE, EnumValuesIncorrect);
|
|
|
|
void wxCheckBox::DoSet3StateValue(wxCheckBoxState state)
|
|
{
|
|
m_state = state;
|
|
if ( !IsOwnerDrawn() )
|
|
::SendMessage(GetHwnd(), BM_SETCHECK, (WPARAM) state, 0);
|
|
else // owner drawn buttons don't react to this message
|
|
Refresh();
|
|
}
|
|
|
|
wxCheckBoxState wxCheckBox::DoGet3StateValue() const
|
|
{
|
|
return m_state;
|
|
}
|
|
|
|
bool wxCheckBox::MSWCommand(WXUINT cmd, WXWORD WXUNUSED(id))
|
|
{
|
|
if ( cmd != BN_CLICKED && cmd != BN_DBLCLK )
|
|
return false;
|
|
|
|
// first update the value so that user event handler gets the new checkbox
|
|
// value
|
|
|
|
// ownerdrawn buttons don't manage their state themselves unlike usual
|
|
// auto checkboxes so do it ourselves in any case
|
|
wxCheckBoxState state;
|
|
if ( Is3rdStateAllowedForUser() )
|
|
{
|
|
state = (wxCheckBoxState)((m_state + 1) % 3);
|
|
}
|
|
else // 2 state checkbox (at least from users point of view)
|
|
{
|
|
// note that wxCHK_UNDETERMINED also becomes unchecked when clicked
|
|
state = m_state == wxCHK_UNCHECKED ? wxCHK_CHECKED : wxCHK_UNCHECKED;
|
|
}
|
|
|
|
DoSet3StateValue(state);
|
|
|
|
|
|
// generate the event
|
|
wxCommandEvent event(wxEVT_CHECKBOX, m_windowId);
|
|
|
|
event.SetInt(state);
|
|
event.SetEventObject(this);
|
|
ProcessCommand(event);
|
|
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// owner drawn checkboxes support
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int wxCheckBox::MSWGetButtonStyle() const
|
|
{
|
|
return HasFlag(wxCHK_3STATE) ? BS_3STATE : BS_CHECKBOX;
|
|
}
|
|
|
|
void wxCheckBox::MSWOnButtonResetOwnerDrawn()
|
|
{
|
|
// ensure that controls state is consistent with internal state
|
|
DoSet3StateValue(m_state);
|
|
}
|
|
|
|
int wxCheckBox::MSWGetButtonCheckedFlag() const
|
|
{
|
|
switch ( Get3StateValue() )
|
|
{
|
|
case wxCHK_CHECKED:
|
|
return wxCONTROL_CHECKED;
|
|
|
|
case wxCHK_UNDETERMINED:
|
|
return wxCONTROL_PRESSED;
|
|
|
|
case wxCHK_UNCHECKED:
|
|
// no extra styles needed
|
|
return 0;
|
|
}
|
|
|
|
wxFAIL_MSG( wxT("unexpected Get3StateValue() return value") );
|
|
|
|
return 0;
|
|
}
|
|
|
|
void wxCheckBox::MSWDrawButtonBitmap(wxDC& dc, const wxRect& rect, int flags)
|
|
{
|
|
wxRendererNative::Get().DrawCheckBox(this, dc, rect, flags);
|
|
}
|
|
|
|
#endif // wxUSE_CHECKBOX
|