You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
696 lines
14 KiB
696 lines
14 KiB
//
|
|
// Microsoft Windows Media Technologies
|
|
// Copyright (C) Microsoft Corporation, 1999 - 2001. All rights reserved.
|
|
//
|
|
|
|
//
|
|
// This workspace contains two projects -
|
|
// 1. ProgHelp which implements the Progress Interface
|
|
// 2. The Sample application WmdmApp.
|
|
//
|
|
// ProgHelp.dll needs to be registered first for the SampleApp to run.
|
|
|
|
// Includes
|
|
//
|
|
#include "appPCH.h"
|
|
#include "appRC.h"
|
|
|
|
// Constants
|
|
//
|
|
#define _szWNDCLASS_MAIN "DrmXferAppWnd_Main"
|
|
#define _szMUTEX_APP "DrmXferApplication_Mutex"
|
|
|
|
#define MIN_MAINWND_W 400
|
|
#define SHOWBUFFER 10
|
|
|
|
// Macros
|
|
//
|
|
|
|
// Global variables
|
|
//
|
|
HINSTANCE g_hInst = NULL;
|
|
HWND g_hwndMain = NULL;
|
|
|
|
CStatus g_cStatus;
|
|
CDevices g_cDevices;
|
|
CDevFiles g_cDevFiles;
|
|
CWMDM g_cWmdm;
|
|
BOOL g_bUseOperationInterface = FALSE;
|
|
|
|
// Local variables
|
|
//
|
|
static HANDLE _hMutexDrmXfer = NULL;
|
|
|
|
// Local functions
|
|
//
|
|
static VOID _CleanUp( void );
|
|
static VOID _InitSize( void );
|
|
static VOID _OnSize( HWND hwnd, WPARAM wParam, LPARAM lParam );
|
|
static VOID _OnMove( HWND hwnd, WPARAM wParam, LPARAM lParam );
|
|
|
|
static BOOL _InitWindow( void );
|
|
static BOOL _RegisterWindowClass( void );
|
|
static BOOL _UsePrevInstance( void );
|
|
|
|
// Local non-static functions
|
|
//
|
|
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow );
|
|
BOOL CALLBACK MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
|
|
|
// Command handlers
|
|
//
|
|
#define _nNUM_HANDLERS 5
|
|
|
|
typedef VOID (*HandleFunc) ( WPARAM wParam, LPARAM lParam );
|
|
|
|
static VOID _OnDeviceReset( WPARAM wParam, LPARAM lParam );
|
|
static VOID _OnDeviceClose( WPARAM wParam, LPARAM lParam );
|
|
static VOID _OnViewRefresh( WPARAM wParam, LPARAM lParam );
|
|
static VOID _OnFileDelete( WPARAM wParam, LPARAM lParam );
|
|
static VOID _OnOptionsUseOperationInterface( WPARAM wParam, LPARAM lParam );
|
|
|
|
struct {
|
|
UINT uID;
|
|
HandleFunc pfnHandler;
|
|
}
|
|
_handlers[ _nNUM_HANDLERS ] =
|
|
{
|
|
{ IDM_DEVICE_RESET, _OnDeviceReset },
|
|
{ IDM_CLOSE, _OnDeviceClose },
|
|
{ IDM_REFRESH, _OnViewRefresh },
|
|
{ IDM_DELETE, _OnFileDelete },
|
|
{ IDM_OPTIONS_USE_OPERATION_INTERFACE, _OnOptionsUseOperationInterface },
|
|
};
|
|
|
|
|
|
//
|
|
//
|
|
int WINAPI WinMain(HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
WPARAM wParam;
|
|
|
|
g_hInst = hInstance;
|
|
|
|
InitCommonControls();
|
|
|
|
if( _UsePrevInstance() )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Initialize COM
|
|
//
|
|
ExitOnFail( CoInitialize(NULL) );
|
|
|
|
// Initialize registry
|
|
//
|
|
SetRegistryParams( g_hInst, HKEY_LOCAL_MACHINE );
|
|
|
|
// Initialize the local environment and windows
|
|
//
|
|
ExitOnFalse( _RegisterWindowClass() );
|
|
ExitOnFalse( _InitWindow() );
|
|
|
|
// Initialize the WMDM
|
|
//
|
|
ExitOnFail( g_cWmdm.Init());
|
|
|
|
// Enter message pump until app is closed
|
|
//
|
|
wParam = DoMsgLoop( TRUE );
|
|
|
|
// Uninitialize COM
|
|
//
|
|
CoFreeUnusedLibraries();
|
|
CoUninitialize();
|
|
|
|
return (int)wParam;
|
|
|
|
lExit:
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK WndProc_Main(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
WORD wId = LOWORD( (DWORD)wParam );
|
|
WORD wNotifyCode = HIWORD( (DWORD)wParam );
|
|
|
|
switch( uMsg )
|
|
{
|
|
case WM_CREATE:
|
|
PostMessage( hWnd, WM_DRM_INIT, 0, 0 );
|
|
break;
|
|
|
|
case WM_DRM_INIT:
|
|
_OnViewRefresh( 0, 0 );
|
|
break;
|
|
|
|
case WM_DRM_DELETEITEM:
|
|
_OnFileDelete( 0, 0 );
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
// Menu item selected
|
|
if( BN_CLICKED == wNotifyCode || 0 == wNotifyCode || 1 == wNotifyCode )
|
|
{
|
|
INT i;
|
|
|
|
for( i=0; i < _nNUM_HANDLERS; i++ )
|
|
{
|
|
if( wId == _handlers[i].uID )
|
|
{
|
|
(*_handlers[i].pfnHandler)( wParam, lParam );
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_ENDSESSION:
|
|
if( (BOOL)wParam )
|
|
{
|
|
// shutting down
|
|
_CleanUp();
|
|
}
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
_OnSize( hWnd, wParam, lParam );
|
|
return 0;
|
|
|
|
case WM_SYSCOMMAND:
|
|
if( SC_MAXIMIZE == wParam )
|
|
{
|
|
_OnSize( hWnd, wParam, lParam );
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
_CleanUp();
|
|
PostQuitMessage( 0 );
|
|
break;
|
|
|
|
case WM_MOVE:
|
|
_OnMove( hWnd, wParam, lParam );
|
|
return 0;
|
|
|
|
case WM_KEYDOWN:
|
|
if( wParam == VK_F5 )
|
|
{
|
|
_OnViewRefresh( 0, 0 );
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_GETMINMAXINFO:
|
|
{
|
|
LPMINMAXINFO lpmmi = (LPMINMAXINFO) lParam;
|
|
|
|
lpmmi->ptMinTrackSize.x = MIN_MAINWND_W;
|
|
}
|
|
return 0;
|
|
|
|
case WM_INITMENU:
|
|
// Enable/disable 'Delete' - command
|
|
EnableMenuItem( (HMENU)wParam, IDM_DELETE, MF_BYCOMMAND |
|
|
(g_cDevFiles.OkToDelete()) ? MF_ENABLED : MF_GRAYED );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
|
|
VOID _OnViewRefresh( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
HRESULT hr;
|
|
HCURSOR hCursorPrev;
|
|
|
|
// Show a wait cursor
|
|
//
|
|
hCursorPrev = SetCursor( LoadCursor(NULL, IDC_WAIT) );
|
|
|
|
// Remove all current files
|
|
//
|
|
g_cDevFiles.RemoveAllItems();
|
|
|
|
// Process messages to allow UI to refresh
|
|
//
|
|
UiYield();
|
|
|
|
// Remove all devices
|
|
//
|
|
g_cDevices.RemoveAllItems();
|
|
|
|
// Reset the device enumerator
|
|
//
|
|
hr = g_cWmdm.m_pEnumDevice->Reset();
|
|
ExitOnFail( hr );
|
|
|
|
// Loop through all devices and add them to the list
|
|
//
|
|
while( TRUE )
|
|
{
|
|
IWMDMDevice *pWmdmDevice;
|
|
CItemData *pItemDevice;
|
|
ULONG ulFetched;
|
|
|
|
hr = g_cWmdm.m_pEnumDevice->Next( 1, &pWmdmDevice, &ulFetched );
|
|
if( hr != S_OK )
|
|
{
|
|
break;
|
|
}
|
|
if( ulFetched != 1 )
|
|
{
|
|
ExitOnFail( hr = E_UNEXPECTED );
|
|
}
|
|
|
|
pItemDevice = new CItemData;
|
|
if( pItemDevice )
|
|
{
|
|
hr = pItemDevice->Init( pWmdmDevice );
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
g_cDevices.AddItem( pItemDevice );
|
|
}
|
|
else
|
|
{
|
|
delete pItemDevice;
|
|
}
|
|
}
|
|
|
|
pWmdmDevice->Release();
|
|
}
|
|
|
|
// Update the device portion of the status bar
|
|
//
|
|
g_cDevices.UpdateStatusBar();
|
|
|
|
// Update the file portion of the status bar
|
|
//
|
|
g_cDevFiles.UpdateStatusBar();
|
|
|
|
// Use the default selection
|
|
//
|
|
g_cDevices.UpdateSelection( NULL, FALSE );
|
|
|
|
// Return cursor to previous state
|
|
//
|
|
SetCursor( hCursorPrev );
|
|
|
|
lExit:
|
|
|
|
return;
|
|
}
|
|
|
|
VOID _OnDeviceReset( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
CProgress cProgress;
|
|
CItemData *pItemDevice;
|
|
HRESULT hr;
|
|
HTREEITEM hItem;
|
|
|
|
// Get the selected device to reset
|
|
//
|
|
hItem = g_cDevices.GetSelectedItem( (LPARAM *)&pItemDevice );
|
|
ExitOnNull( hItem );
|
|
ExitOnNull( pItemDevice );
|
|
|
|
// You can only format devices, not individual folders
|
|
//
|
|
ExitOnFalse( pItemDevice->m_fIsDevice );
|
|
|
|
// Create a progress dialog
|
|
//
|
|
ExitOnFalse( cProgress.Create(g_hwndMain) );
|
|
|
|
// Set operation progress values
|
|
//
|
|
cProgress.SetOperation( "Initializing Device..." );
|
|
cProgress.SetDetails( pItemDevice->m_szName );
|
|
cProgress.SetRange( 0, 100 );
|
|
cProgress.SetCount( -1, -1 );
|
|
cProgress.SetBytes( -1, -1 );
|
|
cProgress.Show( TRUE );
|
|
|
|
hr = pItemDevice->m_pStorageGlobals->Initialize( WMDM_MODE_BLOCK, NULL );
|
|
|
|
cProgress.Show( FALSE );
|
|
cProgress.Destroy();
|
|
|
|
lExit:
|
|
|
|
// Refresh the display
|
|
//
|
|
g_cDevices.UpdateSelection( NULL, FALSE );
|
|
}
|
|
|
|
|
|
VOID _OnFileDelete( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
CProgress cProgress;
|
|
HRESULT hr;
|
|
INT i;
|
|
INT *pnSelItems = NULL;
|
|
INT nNumSel;
|
|
|
|
// Get the number of selected items.
|
|
// Exit if there are no items selected.
|
|
//
|
|
nNumSel = 0;
|
|
g_cDevFiles.GetSelectedItems( pnSelItems, &nNumSel );
|
|
ExitOnTrue( 0 == nNumSel );
|
|
|
|
// Allocate space to hold them the selected items
|
|
//
|
|
pnSelItems = new INT[ nNumSel ];
|
|
ExitOnNull( pnSelItems );
|
|
|
|
// Get the selected file(s) to delete
|
|
//
|
|
ExitOnTrue( -1 == g_cDevFiles.GetSelectedItems(pnSelItems, &nNumSel) );
|
|
|
|
// Create a progress dialog
|
|
//
|
|
ExitOnFalse( cProgress.Create(g_hwndMain) );
|
|
|
|
// Set operation progress values
|
|
//
|
|
cProgress.SetOperation( "Deleting Files..." );
|
|
cProgress.SetRange( 0, nNumSel );
|
|
cProgress.SetCount( 0, nNumSel );
|
|
cProgress.SetBytes( -1, -1 );
|
|
|
|
for( i=nNumSel-1; i >= 0; i-- )
|
|
{
|
|
CItemData *pStorage;
|
|
|
|
// Get the storage object for the current item to delete
|
|
//
|
|
pStorage = (CItemData *)ListView_GetLParam( g_cDevFiles.GetHwnd_LV(), pnSelItems[i] );
|
|
|
|
if( NULL != pStorage )
|
|
{
|
|
IWMDMStorageControl *pStorageControl;
|
|
|
|
// Set the name of the object and show the progress dialog
|
|
//
|
|
cProgress.SetDetails( pStorage->m_szName );
|
|
cProgress.IncCount();
|
|
cProgress.IncPos( 1 );
|
|
cProgress.Show( TRUE );
|
|
|
|
hr = pStorage->m_pStorage->QueryInterface(
|
|
IID_IWMDMStorageControl,
|
|
reinterpret_cast<void**>(&pStorageControl)
|
|
);
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
hr = pStorageControl->Delete( WMDM_MODE_BLOCK, NULL );
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
ListView_DeleteItem( g_cDevFiles.GetHwnd_LV(), pnSelItems[i] );
|
|
}
|
|
|
|
pStorageControl->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
cProgress.Show( FALSE );
|
|
cProgress.Destroy();
|
|
|
|
lExit:
|
|
|
|
if( pnSelItems )
|
|
{
|
|
delete [] pnSelItems;
|
|
}
|
|
|
|
// Refresh the device/devicefiles display
|
|
//
|
|
g_cDevices.UpdateSelection( NULL, FALSE );
|
|
}
|
|
|
|
VOID _OnDeviceClose( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
PostMessage( g_hwndMain, WM_CLOSE, (WPARAM)0, (LPARAM)0 );
|
|
}
|
|
|
|
//
|
|
VOID _OnOptionsUseOperationInterface( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
HMENU hMainMenu;
|
|
HMENU hOptionsMenu;
|
|
|
|
// Remember new state
|
|
g_bUseOperationInterface = !g_bUseOperationInterface;
|
|
|
|
// Check uncheck menu
|
|
hMainMenu = GetMenu(g_hwndMain);
|
|
hOptionsMenu = GetSubMenu( hMainMenu, 1 );
|
|
|
|
CheckMenuItem( hOptionsMenu, IDM_OPTIONS_USE_OPERATION_INTERFACE,
|
|
MF_BYCOMMAND |
|
|
(g_bUseOperationInterface ? MF_CHECKED : MF_UNCHECKED));
|
|
}
|
|
|
|
|
|
|
|
BOOL _InitWindow( void )
|
|
{
|
|
BOOL fRet = FALSE;
|
|
CHAR szApp[MAX_PATH];
|
|
|
|
LoadString( g_hInst, IDS_APP_TITLE, szApp, sizeof(szApp) );
|
|
|
|
g_hwndMain = CreateWindowEx(
|
|
0L,
|
|
_szWNDCLASS_MAIN,
|
|
szApp,
|
|
WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | DS_3DLOOK | WS_CLIPCHILDREN,
|
|
0, 0, 0, 0,
|
|
NULL, NULL, g_hInst, NULL
|
|
);
|
|
ExitOnNull( g_hwndMain );
|
|
|
|
ExitOnFalse( g_cDevices.Create(g_hwndMain) );
|
|
|
|
ExitOnFalse( g_cDevFiles.Create(g_hwndMain) );
|
|
|
|
ExitOnFalse( g_cStatus.Create(g_hwndMain) );
|
|
|
|
_InitSize();
|
|
|
|
// Show the window
|
|
//
|
|
ShowWindow( g_hwndMain, SW_SHOW );
|
|
|
|
fRet = TRUE;
|
|
|
|
lExit:
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL _RegisterWindowClass (void)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = WndProc_Main;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = DLGWINDOWEXTRA;
|
|
wc.hInstance = g_hInst;
|
|
wc.hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE(IDI_ICON) );
|
|
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
|
|
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
|
wc.lpszMenuName = MAKEINTRESOURCE( IDR_MENU );
|
|
wc.lpszClassName = _szWNDCLASS_MAIN;
|
|
|
|
return RegisterClass( &wc );
|
|
}
|
|
|
|
|
|
VOID _CleanUp( void )
|
|
{
|
|
if( _hMutexDrmXfer )
|
|
{
|
|
ReleaseMutex( _hMutexDrmXfer );
|
|
CloseHandle( _hMutexDrmXfer );
|
|
}
|
|
|
|
g_cDevices.Destroy();
|
|
|
|
g_cDevFiles.Destroy();
|
|
}
|
|
|
|
|
|
BOOL _UsePrevInstance( void )
|
|
{
|
|
HWND hwnd;
|
|
DWORD dwErr;
|
|
|
|
// Look for the mutex created by another instance of this app
|
|
//
|
|
_hMutexDrmXfer = CreateMutex( NULL, TRUE, _szMUTEX_APP );
|
|
|
|
dwErr = GetLastError();
|
|
|
|
if( !_hMutexDrmXfer )
|
|
{
|
|
// The function failed... don't use this instance
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
// If mutex didn't exist, don't use a previous instance
|
|
//
|
|
if( dwErr != ERROR_ALREADY_EXISTS )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
hwnd = FindWindow( _szWNDCLASS_MAIN, NULL );
|
|
|
|
if( !hwnd )
|
|
{
|
|
// Mutex exists, but the window doesn't?
|
|
//
|
|
ReleaseMutex( _hMutexDrmXfer );
|
|
CloseHandle( _hMutexDrmXfer );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Show main window that already exists
|
|
//
|
|
BringWndToTop( hwnd );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
INT _GetRegSize( UINT uStrID_RegPath, UINT uStrID_DefVal )
|
|
{
|
|
DWORD dwRet;
|
|
|
|
dwRet = GetRegDword_StrTbl(
|
|
IDS_REG_PATH_BASE,
|
|
uStrID_RegPath,
|
|
(DWORD)-1,
|
|
FALSE
|
|
);
|
|
|
|
if( (DWORD)-1 == dwRet && -1 != uStrID_DefVal )
|
|
{
|
|
char szDef[32];
|
|
|
|
LoadString( g_hInst, uStrID_DefVal, szDef, sizeof(szDef) );
|
|
dwRet = (DWORD)atoi( szDef );
|
|
}
|
|
|
|
return (INT) dwRet;
|
|
}
|
|
|
|
|
|
VOID _InitSize( void )
|
|
{
|
|
INT nX, nY, nW, nH;
|
|
|
|
//
|
|
// Get the window position values from the registry
|
|
//
|
|
nX = _GetRegSize( IDS_REG_KEY_XPOS, (UINT)-1 );
|
|
nY = _GetRegSize( IDS_REG_KEY_YPOS, (UINT)-1 );
|
|
nW = _GetRegSize( IDS_REG_KEY_WIDTH, IDS_DEF_WIDTH );
|
|
nH = _GetRegSize( IDS_REG_KEY_HEIGHT, IDS_DEF_HEIGHT );
|
|
|
|
// if the position didn't exist in the registry or
|
|
// the position is off the screen ( +/- nSHOWBUFFER )
|
|
// then center the window, otherwise use the position
|
|
if( nX == -1 || nY == -1
|
|
|| nX + nW < SHOWBUFFER
|
|
|| nX + SHOWBUFFER > GetSystemMetrics(SM_CXSCREEN)
|
|
|| nY + nH < SHOWBUFFER
|
|
|| nY + SHOWBUFFER > GetSystemMetrics(SM_CYSCREEN)
|
|
)
|
|
{
|
|
SetWindowPos( g_hwndMain, NULL, 0, 0, nW, nH, SWP_NOMOVE | SWP_NOZORDER );
|
|
CenterWindow( g_hwndMain, NULL );
|
|
}
|
|
else
|
|
{
|
|
SetWindowPos( g_hwndMain, NULL, nX, nY, nW, nH, SWP_NOZORDER );
|
|
}
|
|
}
|
|
|
|
VOID _OnSize( HWND hwnd, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
WINDOWPLACEMENT wndpl;
|
|
|
|
wndpl.length = sizeof( WINDOWPLACEMENT );
|
|
|
|
if( GetWindowPlacement(hwnd, &wndpl) )
|
|
{
|
|
DWORD dwW = wndpl.rcNormalPosition.right - wndpl.rcNormalPosition.left;
|
|
DWORD dwH = wndpl.rcNormalPosition.bottom - wndpl.rcNormalPosition.top;
|
|
RECT rcMain;
|
|
|
|
WriteRegDword_StrTbl( IDS_REG_PATH_BASE, IDS_REG_KEY_WIDTH, dwW );
|
|
WriteRegDword_StrTbl( IDS_REG_PATH_BASE, IDS_REG_KEY_HEIGHT, dwH );
|
|
|
|
GetClientRect( hwnd, &rcMain );
|
|
|
|
// set the position and size of the device window
|
|
//
|
|
g_cDevices.OnSize( &rcMain );
|
|
|
|
// set the position and size of the device files window
|
|
//
|
|
g_cDevFiles.OnSize( &rcMain );
|
|
|
|
// set the position of the status bar
|
|
//
|
|
g_cStatus.OnSize( &rcMain );
|
|
|
|
}
|
|
}
|
|
|
|
VOID _OnMove( HWND hwnd, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
WINDOWPLACEMENT wndpl;
|
|
|
|
if( hwnd != g_hwndMain )
|
|
{
|
|
return;
|
|
}
|
|
|
|
wndpl.length = sizeof(WINDOWPLACEMENT);
|
|
|
|
if( GetWindowPlacement(hwnd, &wndpl) )
|
|
{
|
|
WriteRegDword_StrTbl(
|
|
IDS_REG_PATH_BASE,
|
|
IDS_REG_KEY_XPOS,
|
|
wndpl.rcNormalPosition.left
|
|
);
|
|
WriteRegDword_StrTbl(
|
|
IDS_REG_PATH_BASE,
|
|
IDS_REG_KEY_YPOS,
|
|
wndpl.rcNormalPosition.top
|
|
);
|
|
}
|
|
}
|
|
|