[SNDVOL32] Add the small master dialog
[reactos.git] / base / applications / sndvol32 / dialog.c
index 1c83b61..08fd6d1 100644 (file)
@@ -1,17 +1,21 @@
 /*
  * COPYRIGHT:   See COPYING in the top level directory
  * PROJECT:     ReactOS Sound Volume Control
- * FILE:        subsys/system/sndvol32/dialog.c
+ * FILE:        base/applications/sndvol32/dialog.c
  * PROGRAMMERS: Johannes Anderwald
  */
 
 #include "sndvol32.h"
 
-#include <wingdi.h>
 
-#define XLEFT (30)
-#define XTOP (20)
-#define DIALOG_VOLUME_SIZE (150)
+VOID
+ConvertRect(LPRECT lpRect, UINT xBaseUnit, UINT yBaseUnit)
+{
+    lpRect->left = MulDiv(lpRect->left, xBaseUnit, 4);
+    lpRect->right = MulDiv(lpRect->right, xBaseUnit, 4);
+    lpRect->top = MulDiv(lpRect->top, yBaseUnit, 8);
+    lpRect->bottom = MulDiv(lpRect->bottom, yBaseUnit, 8);
+}
 
 LPVOID
 LoadDialogResource(
@@ -66,7 +70,9 @@ AddDialogControl(
     IN LPRECT DialogOffset,
     IN PDLGITEMTEMPLATE DialogItem,
     IN DWORD DialogIdMultiplier,
-    IN HFONT hFont)
+    IN HFONT hFont,
+    UINT xBaseUnit,
+    UINT yBaseUnit)
 {
     RECT rect;
     LPWORD Offset;
@@ -75,12 +81,18 @@ AddDialogControl(
     DWORD wID;
 
     /* initialize client rectangle */
-    rect.left = DialogItem->x + DialogOffset->left;
-    rect.top = DialogItem->y + DialogOffset->top;
-    rect.right = DialogItem->cx;
-    rect.bottom = DialogItem->cy;
+    rect.left = DialogItem->x;
+    rect.top = DialogItem->y;
+    rect.right = DialogItem->x + DialogItem->cx;
+    rect.bottom = DialogItem->y + DialogItem->cy;
 
-    //MapDialogRect(hwndDialog, &rect);
+    /* Convert Dialog units to pixes */
+    ConvertRect(&rect, xBaseUnit, yBaseUnit);
+
+    rect.left += DialogOffset->left;
+    rect.right += DialogOffset->left;
+    rect.top += DialogOffset->top;
+    rect.bottom += DialogOffset->top;
 
     /* move offset after dialog item */
     Offset = (LPWORD)(DialogItem + 1);
@@ -104,7 +116,7 @@ AddDialogControl(
             default:
                /* FIXME */
                assert(0);
-               ClassName = 0;
+               ClassName = NULL;
         }
     }
     else
@@ -112,12 +124,15 @@ AddDialogControl(
         /* class name is encoded as string */
         ClassName = (LPWSTR)Offset;
 
-        /* adjust offset */
-        Offset += wcslen(ClassName) + 1;
+        /* move offset to the end of class string */
+        Offset += wcslen(ClassName);
 
-        /* get offset */
+        /* get window name */
         WindowName = (LPWSTR)(Offset + 1);
     }
+    
+    /* move offset past class type/string */
+    Offset++;
 
     if (DialogItem->id == MAXWORD)
     {
@@ -137,8 +152,8 @@ AddDialogControl(
                            DialogItem->style,
                            rect.left,
                            rect.top,
-                           rect.right,
-                           rect.bottom,
+                           rect.right - rect.left,
+                           rect.bottom - rect.top,
                            hwndDialog,
                            (HMENU)(wID),
                            hAppInstance,
@@ -176,16 +191,8 @@ AddDialogControl(
 
     if (WindowName != NULL)
     {
-        /* position offset to start of name */
-        Offset++;
-
-        /* move offset past name */
-        Offset += wcslen((LPWSTR)Offset) + 1;
-    }
-    else
-    {
-        /* no name so just adjust offset */
-        Offset++;
+        /* move offset past window name */
+        Offset += wcslen(WindowName) + 1;
     }
 
     /* check if there is additional data */
@@ -196,7 +203,8 @@ AddDialogControl(
     }
     else
     {
-        /* add data offset */
+        /* FIXME: Determine whether this should be "Offset += 1 + *Offset" to explicitly skip the data count too. */
+        /* skip past additional data */
         Offset += *Offset;
     }
 
@@ -211,35 +219,75 @@ VOID
 LoadDialogControls(
     IN PMIXER_WINDOW MixerWindow,
     LPRECT DialogOffset,
-    LPVOID DlgResource,
-    DWORD DialogIdMultiplier)
+    WORD ItemCount,
+    PDLGITEMTEMPLATE DialogItem,
+    DWORD DialogIdMultiplier,
+    UINT xBaseUnit,
+    UINT yBaseUnit)
 {
-    LPDLGTEMPLATE DialogHeader;
-    PDLGITEMTEMPLATE DialogItem;
     LPWORD Offset;
-    WORD FontSize;
-    WCHAR FontName[100];
-    WORD Length, Index;
-    HFONT Font;
-
-    /* get dialog header */
-    DialogHeader = (LPDLGTEMPLATE)DlgResource;
+    WORD Index;
 
     /* sanity check */
-    assert(DialogHeader->cdit);
+    assert(ItemCount);
 
     if (MixerWindow->Window)
-        MixerWindow->Window = (HWND*)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MixerWindow->Window, (MixerWindow->WindowCount + DialogHeader->cdit) * sizeof(HWND));
+        MixerWindow->Window = (HWND*)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MixerWindow->Window, (MixerWindow->WindowCount + ItemCount) * sizeof(HWND));
     else
-        MixerWindow->Window = (HWND*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DialogHeader->cdit * sizeof(HWND));
+        MixerWindow->Window = (HWND*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ItemCount * sizeof(HWND));
     if (!MixerWindow->Window)
     {
         /* no memory */
         return;
     }
 
-    /* now walk past the dialog header */
-    Offset = (LPWORD)(DialogHeader + 1);
+    /* enumerate now all controls */
+    for (Index = 0; Index < ItemCount; Index++)
+    {
+        /* add controls */
+        Offset = AddDialogControl(MixerWindow->hWnd, &MixerWindow->Window[MixerWindow->WindowCount], DialogOffset, DialogItem, DialogIdMultiplier, MixerWindow->hFont, xBaseUnit, yBaseUnit);
+
+        /* sanity check */
+        assert(Offset);
+
+        /* move dialog item to new offset */
+        DialogItem =(PDLGITEMTEMPLATE)Offset;
+
+        /* increment window count */
+        MixerWindow->WindowCount++;
+    }
+}
+
+VOID
+LoadDialog(
+    IN HMODULE hModule,
+    IN PMIXER_WINDOW MixerWindow,
+    IN LPCWSTR DialogResId,
+    IN DWORD Index)
+{
+    LPDLGTEMPLATE DlgTemplate;
+    PDLGITEMTEMPLATE DlgItem;
+    RECT dialogRect;
+    LPWORD Offset;
+    WORD FontSize;
+    WCHAR FontName[100];
+    WORD Length;
+    int width;
+
+    DWORD units = GetDialogBaseUnits();
+    UINT xBaseUnit = LOWORD(units);
+    UINT yBaseUnit = HIWORD(units);
+
+    /* first load the dialog resource */
+    DlgTemplate = (LPDLGTEMPLATE)LoadDialogResource(hModule, DialogResId, NULL);
+    if (!DlgTemplate)
+    {
+        /* failed to load resource */
+        return;
+    }
+
+    /* Now walk past the dialog header */
+    Offset = (LPWORD)(DlgTemplate + 1);
 
     /* FIXME: support menu */
     assert(*Offset == 0);
@@ -264,61 +312,62 @@ LoadDialogControls(
     /* copy font */
     wcscpy(FontName, (LPWSTR)Offset);
 
-    Font = CreateFontW(FontSize+8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, FontName);
-    assert(Font);
+    if (DlgTemplate->style & DS_SETFONT)
+    {
+        HDC hDC;
 
-    /* move offset after font name */
-    Offset += Length;
+        hDC = GetDC(0);
 
-    /* offset is now at first dialog item control */
-    DialogItem = (PDLGITEMTEMPLATE)Offset;
+        if (!MixerWindow->hFont)
+        {
+            int pixels = MulDiv(FontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
+            MixerWindow->hFont = CreateFontW(-pixels, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, FontName);
+        }
 
-    /* enumerate now all controls */
-    for(Index = 0; Index < DialogHeader->cdit; Index++)
-    {
-        /* add controls */
-        Offset = AddDialogControl(MixerWindow->hWnd, &MixerWindow->Window[MixerWindow->WindowCount], DialogOffset, DialogItem, DialogIdMultiplier, Font);
+        if (MixerWindow->hFont)
+        {
+            SIZE charSize;
+            HFONT hOldFont;
 
-        /* sanity check */
-        assert(Offset);
+            hOldFont = SelectObject(hDC, MixerWindow->hFont);
+            charSize.cx = GdiGetCharDimensions(hDC, NULL, &charSize.cy);
+            if (charSize.cx)
+            {
+                xBaseUnit = charSize.cx;
+                yBaseUnit = charSize.cy;
+            }
+            SelectObject(hDC, hOldFont);
+        }
+    }
 
-        /* move dialog item to new offset */
-        DialogItem =(PDLGITEMTEMPLATE)Offset;
+//    assert(MixerWindow->hFont);
 
-        /* increment window count */
-        MixerWindow->WindowCount++;
-    }
-}
+    /* move offset after font name */
+    Offset += Length;
 
-VOID
-LoadDialog(
-    IN HMODULE hModule,
-    IN PMIXER_WINDOW MixerWindow,
-    IN LPCWSTR DialogResId,
-    IN DWORD Index)
-{
-    LPVOID DlgResource;
-    RECT rect;
+    /* offset is now at first dialog item control */
+    DlgItem = (PDLGITEMTEMPLATE)Offset;
 
-    /* first load the dialog resource */
-    DlgResource = LoadDialogResource(hModule, DialogResId, NULL);
+    dialogRect.left = 0;
+    dialogRect.right = DlgTemplate->cx;
+    dialogRect.top = 0;
+    dialogRect.bottom = DlgTemplate->cy;
 
-    if (!DlgResource)
-    {
-        /* failed to load resource */
-        return;
-    }
+    ConvertRect(&dialogRect, xBaseUnit, yBaseUnit);
 
-    /* get window size */
-    GetClientRect(MixerWindow->hWnd, &rect);
+    width = dialogRect.right - dialogRect.left;
 
-    /* adjust client position */
-    rect.left += (Index * DIALOG_VOLUME_SIZE);
+    dialogRect.left += MixerWindow->rect.right;
+    dialogRect.right += MixerWindow->rect.right;
+    dialogRect.top += MixerWindow->rect.top;
+    dialogRect.bottom += MixerWindow->rect.top;
 
+    MixerWindow->rect.right += width;
+    if ((dialogRect.bottom - dialogRect.top) > (MixerWindow->rect.bottom - MixerWindow->rect.top))
+        MixerWindow->rect.bottom = MixerWindow->rect.top + dialogRect.bottom - dialogRect.top;
 
     /* now add the controls */
-    LoadDialogControls(MixerWindow, &rect, DlgResource, Index);
-
+    LoadDialogControls(MixerWindow, &dialogRect, DlgTemplate->cdit, DlgItem, Index, xBaseUnit, yBaseUnit);
 }
 
 BOOL
@@ -332,7 +381,6 @@ EnumConnectionsCallback(
     WCHAR LineName[MIXER_LONG_NAME_CHARS];
     DWORD Flags;
     DWORD wID;
-    RECT rect;
     UINT ControlCount = 0, Index;
     LPMIXERCONTROL Control = NULL;
     HWND hDlgCtrl;
@@ -356,8 +404,10 @@ EnumConnectionsCallback(
           /* is it selected */
           if (Flags != 0x4)
           {
+              int dlgId = (PrefContext->MixerWindow->Mode == SMALL_MODE) ? IDD_SMALL_MASTER : IDD_VOLUME_CTRL;
+
               /* load dialog resource */
-              LoadDialog(hAppInstance, PrefContext->MixerWindow, MAKEINTRESOURCE(IDD_VOLUME_CTRL), PrefContext->Count);
+              LoadDialog(hAppInstance, PrefContext->MixerWindow, MAKEINTRESOURCE(dlgId), PrefContext->Count);
 
               /* get id */
               wID = (PrefContext->Count + 1) * IDC_LINE_NAME;
@@ -366,7 +416,7 @@ EnumConnectionsCallback(
               SetDlgItemTextW(PrefContext->MixerWindow->hWnd, wID, Line->szName);
 
               /* query controls */
-              if (SndMixerQueryControls(Mixer, &ControlCount, Line, &Control) == TRUE)
+              if (SndMixerQueryControls(Mixer, &ControlCount, Line, &Control) != FALSE)
               {
                   /* now go through all controls and update their states */
                   for(Index = 0; Index < ControlCount; Index++)
@@ -435,12 +485,6 @@ EnumConnectionsCallback(
 
               /* increment dialog count */
               PrefContext->Count++;
-
-              /* get application rectangle */
-              GetWindowRect(PrefContext->MixerWindow->hWnd, &rect);
-
-              /* now move the window */
-              MoveWindow(PrefContext->MixerWindow->hWnd, rect.left, rect.top, (PrefContext->Count * DIALOG_VOLUME_SIZE), rect.bottom - rect.top, TRUE);
           }
       }
     }
@@ -452,22 +496,34 @@ LoadDialogCtrls(
     PPREFERENCES_CONTEXT PrefContext)
 {
     HWND hDlgCtrl;
+    RECT statusRect;
 
     /* set dialog count to zero */
     PrefContext->Count = 0;
 
+    SetRectEmpty(&PrefContext->MixerWindow->rect);
+
     /* enumerate controls */
     SndMixerEnumConnections(PrefContext->MixerWindow->Mixer, PrefContext->SelectedLine, EnumConnectionsCallback, (PVOID)PrefContext);
 
-    /* get last line seperator */
+    if (PrefContext->MixerWindow->hStatusBar)
+    {
+        GetWindowRect(PrefContext->MixerWindow->hStatusBar, &statusRect);
+        PrefContext->MixerWindow->rect.bottom += (statusRect.bottom - statusRect.top);
+    }
+
+    /* now move the window */
+    AdjustWindowRect(&PrefContext->MixerWindow->rect, WS_DLGFRAME | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, TRUE);
+    SetWindowPos(PrefContext->MixerWindow->hWnd, HWND_TOP, PrefContext->MixerWindow->rect.left, PrefContext->MixerWindow->rect.top, PrefContext->MixerWindow->rect.right - PrefContext->MixerWindow->rect.left, PrefContext->MixerWindow->rect.bottom - PrefContext->MixerWindow->rect.top, SWP_NOMOVE | SWP_NOZORDER);
+
+    /* get last line separator */
     hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, IDC_LINE_SEP * PrefContext->Count);
 
     if (hDlgCtrl != NULL)
     {
-        /* hide last seperator */
+        /* hide last separator */
         ShowWindow(hDlgCtrl, SW_HIDE);
     }
-
 }
 
 VOID