檔案關聯(Windows SDK)

來源:互聯網
上載者:User

如果將一個資料檔案與一個可執行檔關聯,那麼就可以通過雙擊資料檔案來直接執行可執行檔,比如雙擊以txt為副檔名的文字檔,系統就會自動執行Notepad.exe檔案來編輯它,這就是因為txt檔案是與Notepad.exe檔案關聯的。

檔案關聯是在註冊表的HKEY_CLASSES_ROOT根鍵中設定的。要為某種副檔名設定關聯,需要在HKEY_CLASSES_ROOT根鍵下設定兩個子鍵,第一個子鍵的名稱是“.副檔名”(和資料檔案的副檔名相對應),這個子鍵需要設定預設值,預設值的資料為HKEY_CLASSES_ROOT根鍵下另一個子鍵的名稱,在這個子鍵下可以繼續設定與這種資料檔案關聯的可執行檔名。

如果關聯的操作方式是“開啟”,那麼在第二個子鍵中,可以繼續建立“shell/open/command”子鍵,並把command子鍵的預設值設為可執行檔名,這樣雙擊資料檔案,就會執行這個可執行檔;如果關聯的操作方式是“列印”,那麼可以在第二個子鍵中繼續建立“shell/print/command”子鍵,同樣將command子鍵的預設值設為執行列印操作的可執行檔名。當然,也可以只設定“open”操作的關聯。經過這兩個步驟,檔案關聯就設定好了。

以“*.test”資料檔案為例,要在HKEY_CLASSES_ROOT根鍵下建立一個“.test”子鍵,把它的預設值設定為“testfile”,然後再建立一個“testfile/shell/open/command”子鍵,並把command鍵的預設值設定為指定的可執行檔名。

下面這段代碼就是將“*.test”資料檔案與當前可執行檔進行關聯:

// associate.c
// 本程式將設定註冊表,把.test檔案和本程式關聯起來,關聯成功後,雙擊.test檔案
// windows 將自動開啟本檔案
// 要設定一個程式和特定副檔名的檔案關聯,需要做以下2步
// 1. 在 HKEY_CLASSES_ROOT 下面建立一個以副檔名為鍵名的子鍵,比如,你要關聯.test檔案
//    則需要在它下面建立一個.test的子鍵,然後建立一個預設的索引值,即只有索引值沒有鍵名的鍵
//    這個索引值是建立第2個鍵的鍵名,比如我們取鍵名為testfile
// 2. 在 HKEY_CLASSES_ROOT 下面再建立一個子鍵,這個子鍵是第1步建立的鍵名,如testfile
//    如果你要開啟一個檔案,則在這子鍵下建立shell/open/command子鍵,索引值為:
//    可執行檔名稱 %1
//    
//   建立成功後的結構可能如下:
//   HKEY_CLASSES_ROOT
//         |
//         |---.test (有一個預設的索引值 testfile)[預設 = testfile]
//         |
//         |--- testfile
//                |
//                |--shell
//                     |
//                     |--open
//                         |
//                         |--command (有一個預設的索引值: 如 c:/associate.exe %1)
//                                     [預設 = c:/associate.exe %1]
#include <Windows.h>
#include "resource.h"

HWND    hWinMain = NULL;

char    szKeyEnter[] = TEXT("testfile");
char    szKeyExt1[] = TEXT(".test");
char    szKeyExt2[] = TEXT("testfile//shell//open//command");
char    szParam[] = TEXT("  /"%1/"");

char    szDelSub1[] = TEXT("testfile//shell//open");
char    szDelSub2[] = TEXT("testfile//shell");

void SetAssociate();
void DelAssociate();
BOOL IsAssociate();

LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
{
    DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, 0);
    return 0;
}

void SetAssociate()
{
    HKEY    hKey;
    char    szFileName[MAX_PATH];

    if ( ERROR_SUCCESS == RegCreateKey(HKEY_CLASSES_ROOT, szKeyExt1, &hKey))
    {
        RegSetValueEx(hKey, NULL, 0, REG_SZ, szKeyEnter, sizeof(szKeyEnter));
        RegCloseKey(hKey);
    }

    if ( ERROR_SUCCESS == RegCreateKey(HKEY_CLASSES_ROOT, szKeyExt2, &hKey) )
    {
        GetModuleFileName(NULL, szFileName, sizeof(szFileName));
        lstrcat(szFileName, szParam);
        RegSetValueEx(hKey, NULL, 0, REG_EXPAND_SZ, szFileName, strlen(szFileName) + 1);
        RegCloseKey(hKey);
    }
}

void DelAssociate()
{
    HKEY hKey;
    RegDeleteKey(HKEY_CLASSES_ROOT, szKeyExt1);
    // NT下只能一層一層的刪除
    // testfile//shell//open//command
    if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szDelSub1, 0, KEY_WRITE, &hKey) )
    {
        RegDeleteKey(hKey, "command"); // 刪除command這一層
        RegCloseKey(hKey);
    }
    if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szDelSub2, 0, KEY_WRITE, &hKey))
    {
        RegDeleteKey(hKey, "open"); // 刪除open這一層
        RegCloseKey(hKey);
    }
    if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szKeyEnter, 0, KEY_WRITE, &hKey))
    {
        RegDeleteKey(hKey, "shell"); // 刪除shell這一層
        RegCloseKey(hKey);
    }
    RegDeleteKey(HKEY_CLASSES_ROOT, szKeyEnter); // 刪除testfile這一層
}

BOOL IsAssociate()
{
    HKEY    hKey;
    
    if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szKeyExt1, 0, KEY_WRITE, &hKey) )
    {
        RegCloseKey(hKey);
        return TRUE;
    }
    return FALSE;
}

LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch ( uMsg )
    {
    case WM_CLOSE:
        EndDialog(hWnd, 0);
        break;
    case WM_INITDIALOG:
        hWinMain = hWnd;
        if ( IsAssociate() )
        {
            CheckDlgButton(hWnd, IDC_ASSOCIATE, BST_CHECKED);
        }
        break;
    case WM_COMMAND:
        if ( LOWORD(wParam) == IDC_ASSOCIATE &&
             HIWORD(wParam) == BN_CLICKED )
        {
            if ( IsDlgButtonChecked(hWinMain, IDC_ASSOCIATE) )
                SetAssociate();
            else
                DelAssociate();
        }
        break;
    default:
        return FALSE;
    }
    return TRUE;
}

// resource.h
#define IDD_MAIN                        101
#define IDC_ASSOCIATE                   1000
#define IDC_STATIC                      -1

// associate.rc
#include "resource.h"
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_MAIN DIALOG DISCARDABLE  0, 0, 143, 73
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "檔案關聯樣本"
FONT 10, "宋體"
BEGIN
    CONTROL         "將本程式關聯到 .test 檔案",IDC_ASSOCIATE,"Button",
                    BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,7,129,18
    LTEXT           "說明:關聯之後,當你雙擊 .test檔案的時候,windows會自動開啟本程式,取消關聯,把前面的勾去掉即可",
                    IDC_STATIC,7,31,129,35
END

當程式運行起來之後,你選中複選框之後,就將本程式和.test檔案關聯起來了。這時候你可以關閉程式,然後隨便建立一個空的.test檔案,比如a.test,你雙擊一下這個a.test檔案,你發現本程式被啟動起來了,然後你取消複選框關閉程式,再雙擊a.test你發現程式就不會再啟動。這是一個簡單的關聯實現。你可以參照本程式,設計出更複雜的關聯,甚至可以將關聯的檔案表徵圖也改掉。

本程式理論部分來源於羅雲彬32位組合語言一書,原始碼也是由組合語言改寫而來。查看該程式的彙編版本,可以參看此書。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.