⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mciwnd.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * Copyright 2000 Eric Pouech
 * Copyright 2003 Dmitry Timoshkov
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * FIXME:
 * Add support for all remaining MCI_ commands and MCIWNDM_ messages.
 * Add support for MCIWNDF_RECORD.
 */

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "winternl.h"
#include "vfw.h"
#include "digitalv.h"
#include "commctrl.h"
#include "wine/unicode.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(mci);

extern HMODULE MSVFW32_hModule;
static const WCHAR mciWndClassW[] = {'M','C','I','W','n','d','C','l','a','s','s',0};

typedef struct
{
    DWORD       dwStyle;
    MCIDEVICEID mci;
    HDRVR       hdrv;
    int         alias;
    UINT        dev_type;
    UINT        mode;
    long        position;
    SIZE        size; /* size of the original frame rect */
    int         zoom;
    LPWSTR      lpName;
    HWND        hWnd, hwndOwner;
    UINT        uTimer;
    MCIERROR    lasterror;
    WCHAR       return_string[128];
    WORD        active_timer, inactive_timer;
} MCIWndInfo;

static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);

#define CTL_PLAYSTOP    0x3200
#define CTL_MENU        0x3201
#define CTL_TRACKBAR    0x3202

/***********************************************************************
 *                MCIWndRegisterClass                [MSVFW32.@]
 *
 * NOTE: Native always uses its own hInstance
 */
BOOL VFWAPIV MCIWndRegisterClass(void)
{
    WNDCLASSW wc;

    /* Since we are going to register a class belonging to MSVFW32
     * and later we will create windows with a different hInstance
     * CS_GLOBALCLASS is needed. And because the second attempt
     * to register a global class will fail we need to test whether
     * the class was already registered.
     */
    wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC | CS_GLOBALCLASS;
    wc.lpfnWndProc = MCIWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = sizeof(MCIWndInfo*);
    wc.hInstance = MSVFW32_hModule;
    wc.hIcon = 0;
    wc.hCursor = LoadCursorW(0, MAKEINTRESOURCEW(IDC_ARROW));
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = mciWndClassW;

    if (RegisterClassW(&wc)) return TRUE;
    if (GetLastError() == ERROR_CLASS_ALREADY_EXISTS) return TRUE;

    return FALSE;
}

/***********************************************************************
 *                MCIWndCreateW                                [MSVFW32.@]
 */
HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
                           DWORD dwStyle, LPCWSTR szFile)
{
    TRACE("%p %p %lx %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));

    MCIWndRegisterClass();

    if (!hInstance) hInstance = GetModuleHandleW(0);

    if (hwndParent)
        dwStyle |= WS_VISIBLE | WS_BORDER /*| WS_CHILD*/;
    else
        dwStyle |= WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;

    return CreateWindowExW(0, mciWndClassW, NULL,
                           dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
                           0, 0, 300, 0,
                           hwndParent, 0, hInstance, (LPVOID)szFile);
}

/***********************************************************************
 *                MCIWndCreate                [MSVFW32.@]
 *                MCIWndCreateA                [MSVFW32.@]
 */
HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
                           DWORD dwStyle, LPCSTR szFile)
{
    HWND ret;
    UNICODE_STRING fileW;

    if (szFile)
        RtlCreateUnicodeStringFromAsciiz(&fileW, szFile);
    else
        fileW.Buffer = NULL;

    ret = MCIWndCreateW(hwndParent, hInstance, dwStyle, fileW.Buffer);

    RtlFreeUnicodeString(&fileW);
    return ret;
}

static inline void MCIWND_notify_mode(MCIWndInfo *mwi)
{
    if (mwi->dwStyle & MCIWNDF_NOTIFYMODE)
    {
        UINT new_mode = SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0);
        if (new_mode != mwi->mode)
        {
            mwi->mode = new_mode;
            SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMODE, (WPARAM)mwi->hWnd, new_mode);
        }
    }
}

static inline void MCIWND_notify_pos(MCIWndInfo *mwi)
{
    if (mwi->dwStyle & MCIWNDF_NOTIFYPOS)
    {
        long new_pos = SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0);
        if (new_pos != mwi->position)
        {
            mwi->position = new_pos;
            SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYPOS, (WPARAM)mwi->hWnd, new_pos);
        }
    }
}

static inline void MCIWND_notify_size(MCIWndInfo *mwi)
{
    if (mwi->dwStyle & MCIWNDF_NOTIFYSIZE)
        SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYSIZE, (WPARAM)mwi->hWnd, 0);
}

static inline void MCIWND_notify_error(MCIWndInfo *mwi)
{
    if (mwi->dwStyle & MCIWNDF_NOTIFYERROR)
        SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYERROR, (WPARAM)mwi->hWnd, (LPARAM)mwi->lasterror);
}

static void MCIWND_UpdateState(MCIWndInfo *mwi)
{
    WCHAR buffer[1024];

    if (!mwi->mci)
    {
        /* FIXME: get this from resources */
        static const WCHAR no_deviceW[] = {'N','o',' ','D','e','v','i','c','e',0};
        SetWindowTextW(mwi->hWnd, no_deviceW);
        return;
    }

    MCIWND_notify_pos(mwi);

    if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
        SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, mwi->position);

    if (!(mwi->dwStyle & MCIWNDF_SHOWALL))
        return;

    if ((mwi->dwStyle & MCIWNDF_SHOWNAME) && mwi->lpName)
        strcpyW(buffer, mwi->lpName);
    else
        *buffer = 0;

    if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
    {
        static const WCHAR spaceW[] = {' ',0};
        static const WCHAR l_braceW[] = {'(',0};

        if (*buffer) strcatW(buffer, spaceW);
        strcatW(buffer, l_braceW);
    }

    if (mwi->dwStyle & MCIWNDF_SHOWPOS)
    {
        WCHAR posW[64];

        posW[0] = 0;
        SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 64, (LPARAM)posW);
        strcatW(buffer, posW);
    }

    if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
    {
        static const WCHAR dashW[] = {' ','-',' ',0};
        strcatW(buffer, dashW);
    }

    if (mwi->dwStyle & MCIWNDF_SHOWMODE)
    {
        WCHAR modeW[64];

        modeW[0] = 0;
        SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 64, (LPARAM)modeW);
        strcatW(buffer, modeW);
    }

    if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
    {
        static const WCHAR r_braceW[] = {')',0};
        strcatW(buffer, r_braceW);
    }

    TRACE("=> '%s'\n", debugstr_w(buffer));
    SetWindowTextW(mwi->hWnd, buffer);
}

static LRESULT MCIWND_Create(HWND hWnd, LPCREATESTRUCTW cs)
{
    HWND hChld;
    MCIWndInfo *mwi;
    static const WCHAR buttonW[] = {'b','u','t','t','o','n',0};

    mwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mwi));
    if (!mwi) return -1;

    SetWindowLongW(hWnd, 0, (LPARAM)mwi);

    mwi->dwStyle = cs->style;
    /* There is no need to show stats if there is no caption */
    if ((mwi->dwStyle & WS_CAPTION) != WS_CAPTION)
        mwi->dwStyle &= ~MCIWNDF_SHOWALL;

    mwi->hWnd = hWnd;
    mwi->hwndOwner = cs->hwndParent;
    mwi->active_timer = 500;
    mwi->inactive_timer = 2000;
    mwi->mode = MCI_MODE_NOT_READY;
    mwi->position = -1;
    mwi->zoom = 100;

    if (!(mwi->dwStyle & MCIWNDF_NOMENU))
    {
        static const WCHAR menuW[] = {'M','e','n','u',0};

        hChld = CreateWindowExW(0, buttonW, menuW, WS_CHILD|WS_VISIBLE, 32, cs->cy, 32, 32,
                                hWnd, (HMENU)CTL_MENU, cs->hInstance, 0L);
        TRACE("Get Button2: %p\n", hChld);
    }

    if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
    {
        INITCOMMONCONTROLSEX init;
        static const WCHAR playW[] = {'P','l','a','y',0};

        /* adding the other elements: play/stop button, menu button, status */
        hChld = CreateWindowExW(0, buttonW, playW, WS_CHILD|WS_VISIBLE, 0, cs->cy, 32, 32,
                                hWnd, (HMENU)CTL_PLAYSTOP, cs->hInstance, 0L);
        TRACE("Get Button1: %p\n", hChld);

        init.dwSize = sizeof(init);
        init.dwICC = ICC_BAR_CLASSES;
        InitCommonControlsEx(&init);

        hChld = CreateWindowExW(0, TRACKBAR_CLASSW, NULL, WS_CHILD|WS_VISIBLE, 64, cs->cy, cs->cx - 64, 32,
                                hWnd, (HMENU)CTL_TRACKBAR, cs->hInstance, 0L);
        TRACE("Get status: %p\n", hChld);
    }

    /* This sets the default window size */
    SendMessageW(hWnd, MCI_CLOSE, 0, 0);

    if (cs->lpCreateParams)
    {
        LPARAM lParam;

        /* MCI wnd class is prepared to be embedded as an MDI child window */
        if (cs->dwExStyle & WS_EX_MDICHILD)
        {
            MDICREATESTRUCTW *mdics = (MDICREATESTRUCTW *)cs->lpCreateParams;
            lParam = mdics->lParam;
        }
        else
            lParam = (LPARAM)cs->lpCreateParams;

        /* If it's our internal class pointer, file name is a unicode string */
        if (cs->lpszClass == mciWndClassW)
            SendMessageW(hWnd, MCIWNDM_OPENW, 0, lParam);
        else
        {
            /* Otherwise let's try to figure out what string format is used */
            HWND parent = cs->hwndParent;
            if (!parent) parent = GetWindow(hWnd, GW_OWNER);

            SendMessageW(hWnd, IsWindowUnicode(parent) ? MCIWNDM_OPENW : MCIWNDM_OPENA, 0, lParam);
        }
    }

    return 0;
}

static void MCIWND_ToggleState(MCIWndInfo *mwi)
{
    switch (SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0))
    {
    case MCI_MODE_NOT_READY:
    case MCI_MODE_RECORD:
    case MCI_MODE_SEEK:
    case MCI_MODE_OPEN:
        TRACE("Cannot do much...\n");
        break;

    case MCI_MODE_PAUSE:
        SendMessageW(mwi->hWnd, MCI_RESUME, 0, 0);
        break;

    case MCI_MODE_PLAY:
        SendMessageW(mwi->hWnd, MCI_PAUSE, 0, 0);
        break;

    case MCI_MODE_STOP:
        SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -