Bagikan melalui


TN026: Rutinitas DDX dan DDV

Catatan

Catatan teknis berikut belum diperbarui sejak pertama kali disertakan dalam dokumentasi online. Akibatnya, beberapa prosedur dan topik mungkin kedaluarsa atau salah. Untuk informasi terbaru, disarankan agar Anda mencari topik yang menarik dalam indeks dokumentasi online.

Catatan ini menjelaskan arsitektur pertukaran data dialog (DDX) dan validasi data dialog (DDV). Ini juga menjelaskan bagaimana Anda menulis prosedur DDX_ atau DDV_ dan bagaimana Anda dapat memperluas ClassWizard untuk menggunakan rutinitas Anda.

Gambaran Umum Pertukaran Data Dialog

Semua fungsi data dialog dilakukan dengan kode C++. Tidak ada sumber daya khusus atau makro ajaib. Inti mekanisme adalah fungsi virtual yang ditimpa di setiap kelas dialog yang melakukan pertukaran dan validasi data dialog. Ini selalu ditemukan dalam bentuk ini:

void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);   // call base class

    //{{AFX_DATA_MAP(CMyDialog)
        <data_exchange_function_call>
        <data_validation_function_call>
    //}}AFX_DATA_MAP
}

Format khusus komentar AFX memungkinkan ClassWizard menemukan dan mengedit kode dalam fungsi ini. Kode yang tidak kompatibel dengan ClassWizard harus ditempatkan di luar komentar format khusus.

Dalam contoh di atas, <data_exchange_function_call> dalam bentuk:

DDX_Custom(pDX, nIDC, field);

dan <data_validation_function_call> bersifat opsional dan dalam bentuk:

DDV_Custom(pDX, field, ...);

Lebih dari satu pasangan DDX_/DDV_ dapat disertakan dalam setiap DoDataExchange fungsi.

Lihat 'afxdd_.h' untuk daftar semua rutinitas pertukaran data dialog dan rutinitas validasi data dialog yang disediakan dengan MFC.

Data dialog hanyalah bahwa: data anggota di CMyDialog kelas . Ini tidak disimpan dalam struct atau sesuatu yang serupa.

Catatan

Meskipun kami menyebutnya "data dialog", semua fitur tersedia di kelas apa pun yang berasal dari CWnd dan tidak terbatas hanya pada dialog.

Nilai awal data diatur dalam konstruktor C++ standar, biasanya dalam blok dengan //{{AFX_DATA_INIT komentar dan //}}AFX_DATA_INIT .

CWnd::UpdateData adalah operasi yang melakukan inisialisasi dan penanganan kesalahan di sekitar panggilan ke DoDataExchange.

Anda dapat menghubungi CWnd::UpdateData kapan saja untuk melakukan pertukaran dan validasi data. Secara default UpdateData(TRUE) dipanggil dalam handler default CDialog::OnOK dan UpdateData(FALSE) dipanggil dalam default CDialog::OnInitDialog.

Rutinitas DDV_ harus segera mengikuti rutinitas DDX_ untuk bidang tersebut.

Bagaimana Cara Kerjanya

Anda tidak perlu memahami hal berikut untuk menggunakan data dialog. Namun, memahami cara kerjanya di belakang layar akan membantu Anda menulis prosedur pertukaran atau validasi Anda sendiri.

Fungsi DoDataExchange anggota mirip dengan Serialize fungsi anggota - bertanggung jawab untuk mendapatkan atau mengatur data ke/dari formulir eksternal (dalam hal ini kontrol dalam dialog) dari/ke data anggota di kelas. Parameter pDX adalah konteks untuk melakukan pertukaran data dan mirip CArchive dengan parameter dengan CObject::Serialize. pDX (CDataExchangeobjek) memiliki bendera arah seperti CArchive memiliki bendera arah:

  • Jika !m_bSaveAndValidate, muat status data ke dalam kontrol.

  • Jika m_bSaveAndValidate, maka atur status data dari kontrol.

Validasi hanya terjadi ketika m_bSaveAndValidate diatur. Nilai m_bSaveAndValidate ditentukan oleh parameter BOOL ke CWnd::UpdateData.

Ada tiga anggota menarik CDataExchange lainnya:

  • m_pDlgWnd: Jendela (biasanya dialog) yang berisi kontrol. Hal ini untuk mencegah penelepon fungsi global DDX_ dan DDV_ harus meneruskan 'ini' ke setiap rutinitas DDX/DDV.

  • PrepareCtrl, dan PrepareEditCtrl: Menyiapkan kontrol dialog untuk pertukaran data. Menyimpan handel kontrol tersebut untuk mengatur fokus jika validasi gagal. PrepareCtrl digunakan untuk kontrol non-edit dan PrepareEditCtrl digunakan untuk kontrol edit.

  • Fail: Dipanggil setelah memunculkan kotak pesan yang memperingatkan pengguna untuk kesalahan input. Rutinitas ini akan memulihkan fokus ke kontrol terakhir (panggilan terakhir ke PrepareCtrl atau PrepareEditCtrl) dan melemparkan pengecualian. Fungsi anggota ini dapat dipanggil dari rutinitas DDX_ dan DDV_.

Ekstensi Pengguna

Ada beberapa cara untuk memperluas mekanisme DDX/DDV default. Anda dapat:

  • Tambahkan jenis data baru.

    CTime
    
  • Tambahkan prosedur pertukaran baru (DDX_).

    void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm);
    
  • Tambahkan prosedur validasi baru (DDV_).

    void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture);
    // make sure time is in the future or past
    
  • Teruskan ekspresi arbitrer ke prosedur validasi.

    DDV_MinMax(pDX, age, 0, m_maxAge);
    

    Catatan

    Ekspresi arbitrer tersebut tidak dapat diedit oleh ClassWizard dan oleh karena itu harus dipindahkan ke luar komentar format khusus (//{{AFX_DATA_MAP(CMyClass)).

Mintalah DoDataExchange fungsi anggota menyertakan pernyataan C++ yang valid lainnya dengan pertukaran intermix dan panggilan fungsi validasi.

//{{AFX_DATA_MAP(CMyClass)
DDX_Check(pDX, IDC_SEX, m_bFemale);
DDX_Text(pDX, IDC_EDIT1, m_age);
//}}AFX_DATA_MAP
if (m_bFemale)
    DDV_MinMax(pDX, age, 0, m_maxFemaleAge);
else
    DDV_MinMax(pDX, age, 0, m_maxMaleAge);

Catatan

Seperti yang ditunjukkan di atas, kode tersebut tidak dapat diedit oleh ClassWizard dan harus digunakan hanya di luar komentar format khusus.

Dukungan ClassWizard

ClassWizard mendukung subset kustomisasi DDX/DDV dengan memungkinkan Anda mengintegrasikan DDX_ Anda sendiri dan DDV_ rutinitas ke antarmuka pengguna ClassWizard. Melakukan ini hanya bermanfaat biaya jika Anda berencana untuk menggunakan kembali rutinitas DDX dan DDV tertentu dalam proyek atau di banyak proyek.

Untuk melakukan ini, entri khusus dibuat di DDX.CLW (versi Visual C++ sebelumnya menyimpan informasi ini di APSTUDIO. INI) atau dalam proyek Anda . File CLW. Entri khusus dapat dimasukkan baik di bagian [Info Umum] dari proyek Anda. File CLW atau di bagian [ExtraDDX] dari file DDX.CLW di direktori \Program Files\Microsoft Visual Studio\Visual C++\bin. Anda mungkin perlu membuat file DDX.CLW jika belum ada. Jika Anda berencana untuk menggunakan rutinitas DDX_/DDV_ kustom hanya dalam proyek tertentu, tambahkan entri ke bagian [Info Umum] proyek Anda . File CLW sebagai gantinya. Jika Anda berencana untuk menggunakan rutinitas pada banyak proyek, tambahkan entri ke bagian [ExtraDDX] DDX.CLW.

Format umum entri khusus ini adalah:

ExtraDDXCount=n

di mana n adalah jumlah baris ExtraDDX? yang harus diikuti, dari formulir

ExtraDDX?=keys; vb-keys; prompt; jenis; initValue; DDX_Proc [; DDV_Proc; prompt1; arg1 [; prompt2; fmt2]]

Mana? adalah angka 1 - n yang menunjukkan jenis DDX mana dalam daftar yang sedang ditentukan.

Setiap bidang dibatasi oleh karakter ';'. Bidang dan tujuannya dijelaskan di bawah ini.

  • kunci

    Daftar karakter tunggal yang menunjukkan dialog mana yang mengontrol jenis variabel ini diizinkan.

    karakter Kontrol yang diizinkan
    E edit
    C kotak centang dua status
    c kotak centang tri-status
    R tombol radio pertama dalam grup
    L kotak daftar nonsorted
    l kotak daftar terurut
    M kotak kombo (dengan item edit)
    N daftar drop yang tidak diurai
    n daftar drop yang diurutkan
    1 jika sisipan DDX harus ditambahkan ke kepala daftar (defaultnya ditambahkan ke ekor) Ini umumnya digunakan untuk rutinitas DDX yang mentransfer properti 'Kontrol'.
  • vb-keys

    Bidang ini hanya digunakan dalam produk 16-bit untuk kontrol VBX (kontrol VBX tidak didukung dalam produk 32-bit)

  • perintah

    String untuk ditempatkan dalam kotak kombo Properti (tanpa tanda kutip)

  • jenis

    Pengidentifikasi tunggal untuk jenis yang akan dipancarkan dalam file header. Dalam contoh kami di atas dengan DDX_Time, ini akan diatur ke CTime.

  • vb-keys

    Tidak digunakan dalam versi ini dan harus selalu kosong

  • initValue

    Nilai awal — 0 atau kosong. Jika kosong, maka tidak ada baris inisialisasi yang akan ditulis di bagian //{{AFX_DATA_INIT dari file implementasi. Entri kosong harus digunakan untuk objek C++ (seperti , , CTimedan sebagainyaCString) yang memiliki konstruktor yang menjamin inisialisasi yang benar.

  • DDX_Proc

    Pengidentifikasi tunggal untuk prosedur DDX_. Nama fungsi C++ harus dimulai dengan "DDX_," tetapi jangan sertakan "DDX_" dalam <pengidentifikasi DDX_Proc> . Dalam contoh di atas, <pengidentifikasi DDX_Proc> adalah Waktu. Ketika ClassWizard menulis panggilan fungsi ke file implementasi di bagian {{AFX_DATA_MAP, classWizard menambahkan nama ini ke DDX_, sehingga tiba di DDX_Time.

  • komentar

    Komentar untuk ditampilkan dalam dialog untuk variabel dengan DDX ini. Tempatkan teks apa pun yang Anda inginkan di sini, dan biasanya berikan sesuatu yang menjelaskan operasi yang dilakukan oleh pasangan DDX/DDV.

  • DDV_Proc

    Bagian DDV dari entri bersifat opsional. Tidak semua rutinitas DDX memiliki rutinitas DDV yang sesuai. Seringkali, lebih mudah untuk menyertakan fase validasi sebagai bagian integral dari transfer. Ini sering terjadi ketika rutinitas DDV Anda tidak memerlukan parameter apa pun, karena ClassWizard tidak mendukung rutinitas DDV tanpa parameter apa pun.

  • Arg

    Pengidentifikasi tunggal untuk prosedur DDV_. Nama fungsi C++ harus dimulai dengan "DDV_", tetapi jangan sertakan "DDX_" dalam <pengidentifikasi DDX_Proc> .

    arg diikuti oleh 1 atau 2 args DDV:

    • promptN

      String untuk ditempatkan di atas item edit (dengan & untuk akselerator).

    • fmtN

      Format karakter untuk jenis arg, salah satu dari:

      karakter Jenis
      d int
      u int tidak bertanda
      D int panjang (yaitu, panjang)
      U panjang tidak ditandatangani (yaitu, DWORD)
      f float
      F ganda
      s string

Baca juga

Catatan Teknis menurut Angka
Catatan Teknis menurut Kategori