Dynamic
Control Positions
Site Map Feedback
Up Calendar ColorButton CListCtrl DragBar Icons Subclassing

CDragBar

CDragBar implements a vertical bar which may be dragged to reposition other Child Windows.
All the Child Windows are positioned by the owner.
In the parent window create an owner-draw button and subclass it.
For example, in a Dialog, use the Resource Editor to make a Button Control, set [Owner Draw] to checked and in the OnInitDialog have the line:
  DragBar.SubclassDlgItem(IDC_DragBar,this);
You can now give the Bar a default position to go to when the user double-clicks it (0.0=Left, 0.5=Middle, 1.0=Right):
  DragBar.SetDefault(0.3);
If your applications other child window redraw slowly you may wish to stop them redrawing during dragging with:
  DragBar.SetLive(false);
Since you will be redrawing controls during OnSize, you need to know when OnInitDialog has created al its child win
dows with a bool:
  Updated=true;
Now you can set the initial positions by calling Move with no arguments:
  DragBar.Move();
The OnSize Handler would look like this:
void CDragBarTesterDlg::OnSize(UINT nType, int cx, int cy) {
  CDialog::OnSize(nType, cx, cy);
  if(!Updated) return; // Don't access windows before they've been created
  DrawControls();
}
CDragBar passes a special nType to OnSize (SIZE_BAR_DRAGGED) which you can use to filter this message if you need to:
  if(nType==SIZE_BAR_DRAGGED) DrawControls();
This would mean that you wouldn't need the "Updated" flag, and that the controls would only move when you tell them to.
Since there isn't a simple event which signals the end of a resize drag, this only seems useful for non-resizing windows.

DrawControls() should use the GetClientRect and DragBar.GetPostion functions to move and redraw the controls:
  CRect Rect;
  GetClientRect(&Rect);
  int L=DragBar.GetPosition(Rect.Width()); // Left of the DragBar
  const int W=DragBar.Width+1;
  ...more sums...
  GetDlgItem(IDC_EDIT1)->MoveWindow(x,y,cx,cy);
  ...more moves...
Occasionally you'll need to Redraw a control because MoveWindow doesn't make Listboxes redraw their backgrounds etc.
  GetDlgItem(IDC_LIST1)->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); // Don't need to erase background.
You can download an example project here:

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.