Win32 API'sine Giriş. c için WinAPI İşlevleri windows api'sinden türetilmiştir

Nareşti! Nareşti! Bugün her yıl çok fazla iş yapabiliriz Windows. Elveda zavallı konsol!

Şimdiye kadar, C++ sözdizimini iyi bilmek, hata ayıklama ve döngülerle pratik yapmak ve işlevlerin çalışmasını iyi anlamak sizin sorumluluğunuzdadır. Bir deniz savaşına girdiyseniz, devraldığınız şeyi alabilirsiniz.

Ugorskaya giriş formu

Ugrian biçimindeki WinAPI yazımlarına aşina olan tüm kodlar. Bu, kodun nasıl yazıldığı uğruna.

Kimin için, değişikliğin adından önce harf türünün harfini koyun. Değişkenlerin ve işlevlerin adlarındaki tüm kelimeler büyük bir harfle başlar.

Kіlka ekseni prefіksіv:

b - bool türünü değiştirin.
l – uzun tamsayı türüne değiştirildi.
w - word (kelime) yazın - 16 bit. İşaretsiz kısa tür olarak değiştirildi.
dw - çift kelime (alt kelime) - 32 bit. İşaretsiz uzun tür olarak değiştirildi.
sz - sıfırla biten bir satır (sıfırla sonlandırılmış dize). Sürekli galip geldiğimiz harika bir sıra.
p veya lp - gösterge (işaretçi gibi). lp (uzun işaretçi gibi) – bu göstergeler geçmişte kaldı. Aynı zamanda, lp ve p aynı anlama gelir.
h - açıklayıcı (tutamaç gibi).

Örneğin, gösterge şu şekilde eksen olarak adlandırılır:

geçersiz*pData;

Giriş formu Microsoft tarafından onaylanmıştır. Birçok kişi bu şekilde adlandırma değişikliğini eleştiriyor. Ale, buna benzer konuşmalar (lütfen kodlama ile ilgili) büyük şirketlerin hayata ihtiyacı var.

Sanırım sabit seslerin tanımlayıcıları büyük harflerden daha azından oluşuyor: WM_DESTROY. WM_DESTOY - 2 değil, tanım yoluyla atanan sabit.

Ek olarak, winAPI'nin çok sayıda geçersiz kılınmış türü vardır. Üçüncü tarafta eksen - http://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx, her türlü Windows (İngilizce) açıklamalarını bulabilirsiniz.

Ve bir zengin daha, yaku'yu anlamadılar. Göstergeler genellikle NULL değerler bekler. Lütfen sadece 0 olduğuna ve NULL (sıfır) değerine atandığına dikkat edin, bellek yuvasına girmeyin.

Windows API'si (WinAPI)

Windows altındaki tüm programlar özel bir WinAPI programlama arabirimi kullanır. Fonksiyonları ve yapıları mov C'ye yazdıktan sonra programınız Windows'tan çok zengin oluyor.

Windows API, bir işletim sistemiyle çalışmak için büyük bir potansiyele sahiptir. Diyebilirsiniz - sınırlar olmadan.

Yüzlerce WinAPI yeteneğine bakamayız. Yakında daha fazla materyal almak istedim, ancak çok uzun zaman alacaktı ve bataklıklarda WinAPI'yi DirectX'e indirmek "ve birkaç yıl içinde kurtulacaktık. WinAPI'nin açıklaması iki ders alacak (tsey dahil). Pencereler.

Windows altındaki program, DOS altındaki program gibidir, bir ana işlevi vardır. Burada fonksiyon WinMain olarak adlandırılır.

WinAna işlevi

Windows altındaki program aşağıdaki bölümlerden oluşur (her şey WinMain'in ortasında bulunur):

Bu kayıt sınıfının oluşturulması vikna. C++ sınıfları ile kafanız karışmasın. WinAPI C ile yazıldığı için bizim için sınıf yok.
Programın oluşturulması.
Eşliğin tamamlandığı ana döngü.
Obroblyaє povіdomlennya programı vіkonnіy protsessі'da. Vіkonna prosedürü є zvichaynoyu funktієyu.
Chi ekseni, Windows programının temelidir. Dünyanın rahatsız edici dersinin bir kısmını uzatarak, her şey rapor edilir. Programların açıklamasında kaybolursanız, bu noktalara dönün.

Şimdi bildirilen her şeye bir göz atalım:

WinAPI: WNDCLASS Yapısı

Bir yapısal değişiklik WNDCLASS oluşturmamız ve ardından simge sınıfını düzenli olarak kaydetmemiz gerekecek.

Yapının göründüğü gibi eksen:

benim c++ kodum typedef struct ( UINT stili; // WNDPROC pencere stili lpfnWndProc; // pencere prosedürü için gösterge int cbClsExtra; // sınıftan sonra ek bayt. Her zaman 0 int cbWndExtra; // her pencere örneği için ek bayt. Her zaman 0 / program örneği ayarlayın : WinMain'in görünür parametresi olarak HICON hIcon; // program simgesi HCURSOR hCursor; // program imleci HBRUSH hbrBackground; // arka plan rengi LPCTSTR lpszMenuName; // menü adı LPCTSTR lpszClassName; ;

WinAPI ambarındaki WNDCLASS yapısı, oluşturulan pencerenin temel gücünü belirler: simgeler, fare imlecinin türü, pencerenin menüsü nedir, pencerede hangi ek olacak...

її bazında yapıyı doldurduktan sonra son sınıfa kayıt olabilirsiniz. C++ ile aynı sınıf değil. Bu şablonun ne tür bir şablon olduğunu daha iyi anlayabilirsiniz, sisteme kaydettirdiniz ve şimdi bu şablondan yola çıkarak simgenin bir kopyasını oluşturabilirsiniz. Ve tüm bunlar, WNDCLASS'ın yapısal değişiminde belirlediğiniz gibi, gücün anneleri olacaktır.

WinAPI: CreateWindow İşlevi

Büyük sınıfın bu temelde kaydından sonra yepyeni bir program oluşturulur (hemen başka bir noktaya geçtik). Ek CreateWindow işlevi için acele edin. Saldırgan bir prototip olabilir:

benim c++ kodum HWND CreateWindow(LPCTSTR lpClassName, // sınıf adı LPCTSTR lpWindowName, // pencere adı (başlıkta gösterilir) DWORD dwStyle, // pencere stili int x, // ekranın sol kenarının yatay koordinatı int y, // dikey koordinat ekranın üst kenarının int nWidth, // pencere genişliği int nHeight, // pencere yüksekliği HWND hWndParent, // ana pencere HMENU hMenu, // HINSTANCE menü açıklaması hInstance, // LPVOID program örneği lpParam // parametre; olarak ayarlayın BOŞ);

Skin sınıfına (WNDCLASS yapısı) gelince, sınıfın temel gücü belirlenir, burada skin sınıfına özeldir: sınıfın kapsamı, koordinatlar...

Bu işlev, pencerenin açıklamasını döndürür. Açıklamayı açıklayan yardım için pencereye gidebilirsiniz, bu yaklaşık olarak bir tanımlayıcı gibidir.

Saygı gösterin, burada bir sürü yeni tür var. Gerçekten, tüm koku eski, sadece yeniden yazılmış. Örneğin: HWND - Void*'e ​​yeniden atanan PVOID'e yeniden atanan HANDLE türüne yeniden atanmamış. Gerçek derinlere gömülür! Ale hepsi aynı tip HWND - boşlukta tse pokazhchik.

Vіkno birkaç parçadan katlanır. Pratik olarak programın dış görünümünde tıklayabilirsiniz: pencerenin başlığı, sistem menüsü (pencerenin sol üst kısmındaki program simgesine tıklamak gibi), pencereyle çalışmak için üç sistem düğmesi: aç, aç tüm ekranda ve kapatın. Yani, pratik olarak eke bir menü ekleyin. Geri kalanın ekseni kesinlikle bizde olmayacak. Açıkçası, çoğu zaman t.sv tarafından işgal ediliyorum. müşteri alanı, arama ve uygulama koristuvach.

Tse shdo vikonnogo rejimi. DiectX ile uzun süreli uygulamamı vіknі'da bitirmek için - ponoekranny modunu koristuvatisya yapmayacağız.

mesaj işleme

Hepimizin ana sorumluluğu önceki programlar programın Windows altında görünümü

Örneğin, bir koristuvach klavyede bir tuşa basarsa, tuşa basıldığına dair bir hatırlatma oluşturulur. tuşuna bastıysanız program aktifmiş gibi gitmenizi hatırlatalım.

Burada bir podyum (olay) var - bir tuşa basılıyor.

Podіya şunlar olabilir: farenin imlecini hareket ettirmek, programın odağını değiştirmek, klavyenin tuşlarına basmak, pencereyi kapatmak. Hadi zaten zengin. Duje! Bir saniyede, işletim sisteminde onlarca bölme görünebilir.

Böylece eksen, bir bölmeye benziyorsa, işletim sistemi bir uyarı oluşturur: böyle bir tuşa basıldığında, fare imlecinin koordinatları değişti, yeni bir pencere belirdi.

Bildirimler bir işletim sistemi olarak oluşturulabileceği gibi farklı programlar da oluşturulabilir.

Yapıya dikkat edin ve saldırgan bir rütbe gibi görünün:

benim c++ kodum typedef struct tagMSG ( HWND hwnd; // bildirim iptal edilirse pencere UINT mesajı; // bildirim kodu WPARAM wParam; // LPARAM lParam parametresi; // DWORD zamanı parametresi; // alarm meydana gelirse saat, NOKTA pt; / / fare imlecini koordine eder) MSG;

Saygılarımızla, typedef yardımıyla yapılar yeniden tanımlanır.

Bu yapıyı oluşturmak için aşağıdaki kodu hızlandırabilirsiniz:

benim c++ kodum msg.messgae == 2; // msg.message == WM_DESTROY; // WM_DESTROY sabiti ikidir

Alarm kodunun yazılacağı alandır (Im'ya uyarısı, WM_DESTROY sabiti ile eşleştirilir. WM - Windows Mesaj türü (Windows uyarısı). WM_DESTROY - pencere kapatıldığında oluşturulan uyarı kodudur. (yok et - yok et).

Ek sabitler atamaya ve WM_ önekini kullanmaya yardımcı olan kod: WM_CLOSE, WM_CREATE ve diğerleri.

MSG yapısı, HWND benzeri Pencere Kolu (pencere tanımlayıcısı veya pencere açıklaması) türüne sahiptir. Böyle bir şey, bir pencereyi "tanımlamak" gibi. Fiyat, tanımlayıcının (bilet adı) szrazok'u içindir.

Tüm kelimeyi hatırla - tanıtıcı (tanımlayıcı, tanımlayıcı). Windows'ta daha yaygın olduğu açıktır. H - açıklamasına dayanan tüm Windows türleri olabilir: simgenin açıklaması, yazı tipinin açıklaması, program örneğinin açıklaması. Otuz tane var, kaç tane olduğunu hatırlıyorum.

Windows'taki programlar arasındaki tüm etkileşimler, pencerelerin (HWND) ek açıklamaları için kullanılır.

Bir önemli tanım daha var - program açıklaması (HINSTANCE - WinMain'in ilk parametresi) - bu benzersiz program tanımlayıcısıdır, bu nedenle işletim sistemi iki farklı programı karıştıramaz. Tse bir barkod gibidir. Şimdi yoga piznişesine bir göz atalım.

Yani, coristuvach bir tapu olarak çalışıyorsa, oluşturulur ve hatırlanır: pencerenin açıklaması ayarlanır, böylece dikkat çekebilir, bildirim tanımlayıcısı ayarlanır, parametreler ayarlanır, saat (geçerli) belirtilir ve imleç koordinatları belirtilir.

Kimden sonra, tse anma işletim sistemi. Tavsiyemize gelirsek gerekli viknuya göre düzeltilecektir (windows, cilt bakımını açıklamalar için düzeltmenin her zaman mümkün olduğunu bilir). Programa gelmeniz hatırlatılırsa, programı hatırlatmak için siyah renkte olacaktır. Yeni siyaha ulaşmak kolay, ortaya çıkıyor.

Bu saatte, coristuvach bir be-yak-to-diya yapmış olsaydı (bir podia vardı ve üretildi) ve o anda, program tsyu-diya'ya tepki verdiyse ( programı), zengin bir podia vardı. Adzhe yak u cherzy Windows uyandırma bu yüzden gelecekte, program zengin bir şekilde açıklanabilir. İlk kişi için yüzlerce, başka bir kişi için en azından bir çaça olabilir.

Vіkonna prosedürü (Pencere prosedürü - WndProc)

O andan itibaren Prodovzhuєmo, bir hatırlatma olarak, program ağzına kadar rehabilite edildi. Yeni karanlığa iyi geldi, dönüyor. İşleme için cilt programının özel bir işlevi olabilir - bir vicon prosedürü. Buna WndProc (Pencere Prosedürü gibi) denir. Programın ana döngüsünde Viklik vykonnoy prosedürü rastashovaniya ve cilt yineleme döngüsü sırasında vykonuetsya.

Uyarılar (MSG'deki görünüşte yapısal değişiklikler için) şuradan alınır: bu fonksiyon Parametreleri görüntüle: pencerenin açıklaması, güncellemenin kimliği ve iki parametre. Lütfen zaman ve pt alanlarının prosedüre geçirilmediğini unutmayın. Tobto, povіdomlennya vzhe "razіbrane".

Anahtarı devre dışı bırakmak için orta prosedürü kullanın, bu durumda uyarı tanımlayıcısını yeniden kontrol edin. Basit bir vikonnoy prosedürünün popo ekseni (daha fazla iş olacak):

benim c++ kodum// HRESULT ve __stdcall için henüz saygı gönderme. Onlara bir göz atalım. ) // kontrol listesini çöz )

І dinlenme - ana döngü. Vin basittir. Döngünün dış görünüm yinelemesi program tarafından yeniden doğrulanır. Şeytanın bir hatırlatıcısı ve hatırlatıcısı olduğu anda, siyahlardan çekilir. Ardından, döngü zamanında, chergi'den gelen bildirimi tamamlamak için prosedürün sonuna kadar bir takip yapılacaktır.

Eksen parlıyor ve hepsi bugün için. WinAPI programının DOS programından çok daha karmaşık olduğu zaten açık. Daha önce de yazdığım gibi, bir sonraki aşamada çalışan programın kodunu analiz edeceğiz.

Yeni bir proje nasıl oluşturulur. Yeni Proje penceresinde şablonu (şablon) seçin - Win32Project (Win32 Konsol Uygulamasını seçtik). Bu vicon'lardan birinde, bayrağı Boş Proje olarak ayarlamayın ve IDE programı oluşturacaktır.

Project_name.cpp dosyasının koduna saygıyla hayran kalırsanız, o zaman tartıştığımız tüm konuşmaları ortaya çıkaracaksınız: MSG'nin yapısal değişikliği, WNDCLASS yapısının tamamlanması, CreateWindow işlevi tarafından pencerenin oluşturulması, ana program döngüsü. Ek olarak, dosyaya atanmış WndProc işlevi vardır. Anahtarın değiştirilmesi gereken sayıyı değiştirmeliyiz: WM_COMMAND, WM_PAINT, WM_DESTROY. Dosyadaki her şeyi bulun.

Gördüklerimizin dışında, programın birçok ek kodu var. Bir sonraki sürümde program koduna bakacağız, de bude her şeyi görecek. IDE'nin ürettiğinden daha basit ve anlaşılır olacaktır.

API (Uygulama Programlama Arayüzü), yazılım satıcıları tarafından sıklıkla kullanılan bir terim olan bir program programlama arayüzüdür. Tıpkı genişleyen, yeni ve diğer eklentileri eklemenize izin veren bir işlevi olan bir program gibi, bu da programınızın API'sidir. İşlevinizi kabul eden, API'yi onaylayan parametreler ve diğer eklemelere ek olarak parçalar bu işlevle etkileşime girer.

Windows işletim sistemi, Visual FoxPro programları da dahil olmak üzere çeşitli programların Windows ile düşük düzeyde bilgi alışverişi yapmasına izin veren geniş bir özellik yelpazesi sunar. Bu işlevlere Windows API adı verilir. Visual FoxPro programlarında Windows API'sini kullanmak, standart film yöntemlerinin erişemeyeceği özellikleri uygulamanıza olanak tanır.

Visual FoxPro'da Kullanımdan Kaldırılan Windows API İşlevleri

Windows API işlevleri, dinamik olarak bağlantılı kitaplıklara bağlanır (Dinamik Bağlantı Kitaplığı, DLL). Kural olarak, bu tür kitaplıkların dosyaları genişletilebilir. dll. Bundan önce, ekinizden Windows API işlevini nasıl kazanacağınız, suçlusunuz çıplak. İşlevi bildirmek için DECLARE..DLL komutu yürütülür:

BİLDİRMEK[ cFunctionType] Fonksiyon adıİÇİNDE KitaplıkAdı ; [cParamType1 [@] ParamName1, cParamType2 [@] ParamName2, ...]

Komut parametreleri:

cFunctionType
İşlev tarafından döndürülecek veri türünü belirten bağlayıcı olmayan bir parametre:

cFunctionType Rozmir,
bayt
Tanım
kısa 16 bit tam sayı
Tamsayı, Uzun 4 32 bit tam sayı
Bekar 4 32 haneli konuşma numarası
Çift 8 64 bit konuşma numarası
Sicim - Karakter satırı

Fonksiyon adı
im'ya DLL kitaplığında işlev görür. Bu işlev büyük/küçük harf duyarlıdır, bu nedenle GetDC ve GETDC tamamen farklı işlevlerin adlarıdır.

KitaplıkAdı
işlevin değiştirildiği DLL kitaplığının adı. Kernel32.dll, Gdi32.dll, User32.dll, Mpr.dll ve Advapi32.dll kütüphaneleri için WIN32API ile eşanlamlı bir isim seçmek mümkündür.

Takma ad
Takma adlarınızı kazanmak için işlevin adını değiştirmenize izin veren bağlayıcı olmayan bir parametre. Takma adın işlevi adına yazılması, karakter kaydına duyarlı değildir. Genel bir kural olarak, API işlevleri (veya sizin) Visual FoxPro işlevlerinin adlarıyla çağrılırsa, diğer adın üzerine yazılır.

cParamType
Geçirilen işlev verilerinin türünü belirtin:

Parametre, değerler ve mesajlar için iletilebilir. Parametrenin istek üzerine iletildiğini belirtmek için "@" sembolü kullanılır.

Visual FoxPro, Uzun ve Tamsayı veri türleri arasında ayrım yapmıyor gibi görünüyor. Tamsayı türünü bir işaretle imzalamak için Tamsayı türünü ve işaretsiz tamsayılar için Uzun türünü arayın.

ParamName
neobov'yazykovy parametresi, scho tamamen tanımlayıcı niteliktedir ve kural olarak yoksayılır.

C programım tarafından yazılan vtim ve Windows gibi tüm Windows API işlevleri. Bu nedenle, Visual FoxPro'da API işlevlerinin nasıl doğru bir şekilde hackleneceğini anlamak için (en azından C ile yazmak, o çekirdeği almak), C ve Windows'ta veri yazmayı biliyoruz ve daha az önemli değil, Pererahuvannya, yapılar ve şovmenler gibi bu tür haraçlara bir göz atalım. Ek olarak, bu tür işlev prototiplerinin C'de olduğunu biliyorsunuz ve bu nedenle, işlev prototipinin MSDN'deki açıklamasına dayanarak, bunu DECLARE..DLL komutunda doğru bir şekilde bildirin.

Temel Veri Tipleri Сi

Benim C programlamamı biliyorsanız, o zaman yenide farklı veri türleri oluşturmanın ne kadar kolay olduğunu bilirsiniz. Aşağıdaki kodu yazmanız yeterlidir:

Typedef int INT32;

ve sahip olduğunuz eksen, int türüne daha çok benzeyen yeni bir INT32 türüdür. Ale, bir bakacağım Cі, tse zovsim farklı şekiller INT32 değişiklik tipine int değişiklik tipinin değerini cehenneme atamayı deneyin!

Veri türlerinin bolluğu, perakendecilerin API yardımıyla programlamanın önemli olduğunu düşünmelerini zorlaştırıyor. Ama öyle değil! C'de aşağıdaki veri türlerini kazanmak önemlidir:

    tip karakter - ANSI formatı için sembol. Son 8 deşarj olabilir (bir bayt).

    tip wchar - Unicode karakter. 16 deşarj (iki bayt) olabilir.

    tip int - sayıların sayısı. Koku, C'de üç tipe ayrılır: int, kısa intі uzun int. Kısa bir süre önce çalmayı kes kısaі uzun. Tip kısa- tse 16-bit, ancak tipi intі uzun- 32 basamaklı sayılar.

    tip batmadan yüzmek- Bir atış parçacığı yapmak için konuşma numaraları. Mayut dozhina 32 deşarj (4 bayt).

    tip çift- Alt değişken doğruluğunun konuşma numaraları. Mayut dozhina 64 deşarj (8 bayt).

    tip Sıralama - geri ödenen haraç türü.

    tip geçersiz değerlerin bilişi için vikoristovuєtsya, değeri anlamayan bir sıfır noktası bulmak için scho.

    tip Işaretçi - şovmen; rezil sensi'den gelen bilgiler için misilleme yapmak - diğer Cі türleri gibi; natomist, skin indikatörü hafızanın ortasında gerçek verilerin alındığı adreslere sahiptir. Dohina 32 deşarj olabilir (4 bayt).

Şaşırtıcı değil, satır türü Cі vіdsutnіy. Aslında, tüm satırlar aynı sembol dizisiyle sunulur.

Deyakі tipi, imzasız gibi sessiz olabilir. değiştirici imzasız (işaretsiz) saldırgan haraç türleri ile vykoristovuetsya: karakter, kısa, intі uzun.

Örneğin, Сi'deki değişikliği dile getirmenin başlangıcı:

imzalı int im'ya_zminnoy;

değiştirildiği anlamına gelir - işaretsiz bir 32 bit tam sayı.

değiştirici const türe atanan değerin bir sabit tarafından değiştirildiğini, böylece değerin değiştirilebileceğini gösterin.

geri alma türü Sıralama po'yazuє zі zmіnnoyu zmіnnoyu іmenovannykh sabitleri, zvіn sabitleri listeleme. Goloshennya tipi, scho perekahovuetsya, şöyle görünüyor:

Sıralama etiket_alanı { const1, const2, ... } değiştirmek;

Yakscho etiket_alanı alçalır, daha sonra kıvırcık yayı kapattıktan sonra belirtmek gerekir değiştirmek. Yakscho etiket_alanı gösterilir, sonra belirtilmez değiştirmek.

Tarihsel olarak, enum türü int türüne eşittir - bellekte 4 bayt ödünç alan bir tür ile değiştirilir. Yeniden canlandırılan cilt sabiti, listedeki sıra numarasıyla atanan değer olabilir; numaralandırma sıfırdan başlar. CombineMode'a bir göz atalım:

Enum CombineMode( CombineModeReplace, CombineModeIntersect, CombineModeUnion, CombineModeXor, CombineModeExclude, CombineModeComplement);

Bu geçiş için CombineModeReplace sabiti 0 değerine sahip olabilir, CombineModeIntersect sabiti 1 değerine sahip olabilir ve bu şekilde devam eder; CombineModeComplement sabitinin değeri 5 olabilir.

Geri ödenen sabitlerin değerleri, örneğin saldıran bir popoda olduğu gibi açıkça açık olabilir:

Enum DashCap(DashCapFlat=0, DashCapRound=2, DashCapTriangle=3);

Listelenen veri türleri, Windows API programlamasında olduğu gibi tüm veri türlerinin %99'unu kapsar. Kulağa çok basit gelmiyor, değil mi? API işlevlerinin açıklamaları neden diğer türler tarafından kullanılmalıdır - HWND, HINSTANCE, POINT ve bunlara benzer?

Bunun nedeni, bunlar katı yazım. Bir kez, bir türün değiştirilmesi, yalnızca o türle eşleşiyormuş gibi bu değerleri alabilir. Arka arkaya koçanınızı kaydedip sonra numarayı veremezsiniz. Visual FoxPro'da, adlandırma konusunda memnun etmek için benzer bir yolu simüle etmeye çalışıyor gibiyiz. Örneğin, cName alternatif bir karakter türüdür, nCount ise sayısal bir türdür. Kesin yazım mevcut veri türüne yeni bir ad vererek yeni bir veri türü oluşturmanıza olanak tanır. Yeni bir deri türü, içten kokanlardan bağımsız olarak, diğer türlerle aynı tür gibi görünüyor.

Windows konsepti karmaşıklaştırıyor. Örneğin, LONG türü aslında uzun bir int, UINT türü ise unsigned int'dir. Obidva türleri 32 bit tam sayılardır. Diğer veri türleri, farklı içerme dosyalarına atanır (uzantıları.h olan dosyalar). Visual Studio.NET kullandıysanız, dosyaları klasörde bulabilirsiniz. ..\VC7\PlatformSDK\Dahil\.

Tipi Veri Pencereleri

Nitekim C taban türlerinden hangisinin API işlevinde yer alan veri türünü etkin bir şekilde temsil ettiği, programlama API'sindeki en önemli görevlerden biridir. Bu kuralı eşleştirin: kelimeyi bilemezsiniz şamandıra, çift, karakter veya cadde bir işlev adında veya bir parametrede olabilir veya 32 bitlik bir değer kullanın. Bu alışkanlığı gözden geçirmek uzun bir saat sürecek ve ardından veri türlerini kolayca yeniden çalışacaksınız. Sonraki tabloda, Visual FoxPro işlevi devre dışı bırakıldığında seçilen ana Windows veri türleri ve diğer türler bulunur:

veri tipi
pencereler
Sessizce yazın
fonksiyonlar
Tanım
BOOL Uzun 32 bit tam sayı. 0 yanlış, reshta doğru anlamına gelir.
BOOLE Uzun BOOL ile aynı olanlar.
BAYT Sicim 8 basamaklı sayı
CHAR Sicim 8 basamaklı sayı
CLSID Sicim
RENKLİ Uzun 32 bit tam sayı
DWORD Uzun 32 bit tam sayı
ÇİFT Çift 64 bit konuşma numarası
BATMADAN YÜZMEK Bekar 32 haneli konuşma numarası
GUID Sicim 128 bitlik sayı (16 bayt)
ÜSTESİNDEN GELMEK Uzun
HBITMAP Uzun 32 bit tam sayı işaretsiz sayı
HDC Uzun 32 bit tam sayı işaretsiz sayı
HICON Uzun 32 bit tam sayı işaretsiz sayı
GLOBAL Uzun 32 bit tam sayı işaretsiz sayı
HKL Uzun 32 bit tam sayı işaretsiz sayı
HLOKAL Uzun 32 bit tam sayı işaretsiz sayı
HINSTANCE Uzun 32 bit tam sayı işaretsiz sayı
HRESULT Uzun 32 bit tam sayı işaretsiz sayı
HWND Uzun 32 bit tam sayı işaretsiz sayı
UZUN Uzun 32 bit tam sayı
LPARAM Uzun 32 bit tam sayı işaretsiz sayı
KISA tamsayı 16 bit tam sayı
SIZE_T Uzun 32 bit tam sayı işaretsiz sayı
TCHAR Sicim ANSI dizeleri için CHAR ve Unicode dizeleri için WCHAR ile eşleşir
UÇAR Sicim ANSI kodlamasında karakter
UINT Uzun 32 bit tam sayı işaretsiz sayı
UZUN Uzun 32 bit tam sayı işaretsiz sayı
USHORT tamsayı
UUID Sicim 128 bitlik sayı (16 bayt)
GEÇERSİZ HAYIR önemli değil
WCHAR Sicim UNICODE karakteri
WNDPROC Uzun 32 bit tam sayı işaretsiz sayı
KELİME tamsayı 16 bit tam sayı işaretsiz sayı
WPARAM Uzun 32 bit tam sayı işaretsiz sayı

Vkazivniki

C'de yaygın olarak kullanılan bir diğer kavram ise işaretçilerdir. Gösterge, verilerin toplandığı hafıza alanının adresinin nasıl alınacağı değiştirilir. Gösterge türü her zaman belirttiğiniz veri türüne göre belirlenir; yogo rozmir zavzhdi dorovnyu chotiry baytları. Örneğin, SHORT türünü değiştirmek için bir gösterge, diğer herhangi bir veri türü için bir gösterge olarak tam bir 32 bit sayısıdır. Windows API programlamasında kabul edilen göstergenin açıklaması, Uzun İşaretçi anlamına gelen "LP" veya 32 bit bellek modeliyle çalışan "uzun işaretçi" karakterleriyle başlar. Verilerin suçlu olmadığını belirtmek için "C" (const) sembolünü kullanalım. Adresleri gösterge olarak alınan, değiştirilen veri türünün bir tanımını verdiler. Örneğin, LPDWORD - için gösterge türü değiştir DWORD.

Windows API işlevleri dile getirildiğinde sayısal veriler üzerindeki belirteçler istek üzerine aktarılır. Örnek olarak GetFileSize fonksiyonuna bakalım. Eksen її prototipi (fonksiyon prototipleri hakkında daha fazla bilgi aşağıda tartışılacaktır):

DWORD GetFileSize(HANDLE hFile, // dosya tanıtıcısı LPDWORD lpFileSizeHigh // gösterge);

İşleve iletilen başka bir parametre, dosya boyutunun değerini bayt cinsinden yerleştirecek olan DWORD türünü değiştiren bir parametredir.

Visual FoxPro için duyurulan işlevler:

GetFileSize IN WIN32API Long hFile, Long @ FileSizeHight IN BİLDİRİMİ

Nitekim fonksiyona FileSizeHight parametresi iletilir. yardım için bunun için transfer fayda içindir - tse i є göstergenin transferi.

Satırlarla sağda Skladnishe. Daha önce olduğu gibi, Cі - tse dizisindeki karakter satırları, API işlevlerinin programlanmasında tür sabittir cadde, CHAR türündeki ilk karakter dizisi (isteğe bağlı, tür wstr WCHAR türüne bir dizi karakter atar. Sonraki tablo, karakter satırlarındaki göstergelerin türünü gösterir:

Ekleme türü
üst üste
Tanım
LPSTR Sıfır sonlandırıcı, değiştirilebilen ANSI formatı ile uyumludur. istek üzerine geçti
LPCSTR Sıfır sonlandırıcı, değiştirilemeyen ANSI biçimiyle uyumludur. Değer için geçti
LPTSTR ANSI dizeleri için LPSTR ve UNICODE dizeleri için LPWSTR ile eşleşir. Yardım için geçti.
LPCTSTR ANSI dizeleri için LPSTR ve UNICODE dizeleri için LPWSTR ile eşleşir. Anlam için geçti.
LPWSTR Değiştirilebilen UNICODE satırını boş sonlandırmak için Vkazіvnik. istek üzerine geçti
LPCWSTR Değiştirilemeyen bir UNICODE dizesini boş sonlandırma kılavuzu. Değer için geçti

Karakter verileri üzerindeki belirteçler hem istek hem de değer olarak iletilebilir - sessiz bir Visual FoxPro işlevinde Dize türü zavzhd geçiş kazіvnik sembolik verilerin intikamını alacak şeyi değiştirin. Yalnızca API işlevinin parametrenin değerini değiştirmekten suçlu olması durumunda, istek üzerine karakter verilerinin zafer aktarımı.

yapılar

Yapı, bir bütün halinde kullanılabilen bir dizi farklı tip olarak mümkündür. C'de yapı, anahtar kelimenin yardımıyla oluşturulur. yapı, bundan sonra neobov'yazkove izler etiket alanı(etiket) o liste elementler yapılar:

yapı etiket_alanı { element_type element1; element_type element2; ..... element_type elementN; };

Muhtemelen ve böyle sesli bir yapı:

yapı( element_type element1; element_type element2; ..... element_type elementN; } değiştirmek;

Kimin şaşkın bir günü var etiket alanı anonim bir yapısal tip olarak yaratılmıştır; böyle bir sözdizimi, örneğin saldırgan bir popoda olduğu gibi, bu yapısal türe bir veya daha fazla değişiklik eklemenize izin verir:

Yapı (Kelime wYıl; KELİME wAy; KELİME wDayOfWeek; KELİME wDay; KELİME wSaat; KELİME dakika; KELİME wİkinci; KELİME wMilisaniye; ) SYSTEMTIME, * PSYSTEMTIME;

Yapılar, Visual FoxPro tablo girdilerine benzer. Yani, bir tablo girişi olarak kişiye özel alanların intikamını almak fio,adres,tlfnumber ve e-posta, ardından tlfnumber alanına dönüş için aşağıdaki sözdizimi kullanılır:

Kişisel.tlfnumarası

Öyleyse yapı alanına bakın ve görün:

SYSTEMTIME.wDakika

Visual FoxPro yapılarının oluşumu için karakter satırlarını değiştirmek için değişiklikler yapılır. Örneğin yukarıda baktığınız SYSTEMTIME yapısı için maksimum 16 bayt değiştirmeniz gerekiyor. İlki, alan değerini girmek için iki bayt değişiklik içeriyor wYıl, saldırının iki baytı var - alan değeri wAy, saldırının iki baytı var - alan değeri wDayOfWeek, ve böylece yapı tamamen oluşana kadar. Ve Visual FoxPro'nun API işlevi ortaya çıktığında, yapıyı değiştirmek için değişikliğin geçirildiği parametrenin türü, String türünden kaynaklanır. Sayısal verileri değiştirerek bir satırda nasıl yazılır, yılda biraz bilirsiniz.

Windows API'sini C'de programlarken, yapı göstergesinin açıklaması, LP (Uzun İşaretçi) sembollerini ve ardından yapının adını temel alır. Yani, SYSTEMTIME yapısının göstergesi LPSYSTEMTIME tipidir, POINT yapısının göstergesi LPPOINT tipidir, aynen böyle. Bir bachit gibi, katlanabilir hiçbir şey yok, ancak zavdyaki bu konsept, yapı üzerinde mükemmel derecede çok sayıda gösterge türü.

Aktarılan yapıdaki veriler değişmekten suçlu değilse, böyle bir yapının göstergesi şu şekilde seslendirilir:

SABİT im'ya_yapısı *

Burada CONST değiştiricisi, yapıdaki verilerin değişmediği anlamına gelir ve yapı adından sonraki (*) sembolü, tüm satırın yapı için göstergenin bir açıklaması olduğu anlamına gelir. Bu kanıt uygulaması için, CopyRect işlevinin prototipi, bir yapının diğerindeki bir kopyası olarak:

BOOL CopyRect(LPRECT lprcDst, CONST REKT * lprcSrc);

MSDN'deki fonksiyon prototiplerinin açıklaması

Şimdi, veri türleriyle ilgili her şey az çok netleştiyse, fonksiyonların prototipleri gibi C kavramlarını daha iyi anlayacağız.

ANSI standardına kadar Vіdpovіdno, tüm işlevler ana prototiplerden kaynaklanmaktadır. Fonksiyonun prototipi basittir:

turn_type fonksiyon adı( parametre_türü(iv) parametre_adi(іv));

Prototip tipi VOID olarak belirtildiğinde turn_type, bu, işlevin aynı değerleri döndürmediği anlamına gelir. VOID tipi nasıl atanır? parametre_türü, Ze, fonksiyonun parametrelendirilemeyeceği anlamına gelir.

Kernel32.dll, Gdi32.dll, User32.dll, Mpr.dll ve Advapi32.dll kitaplıklarından önce bulunan Windows API işlevlerinin prototipleri hakkında bilgileri MSDN for Visual Studio.NET'ten bulabilirsiniz:

MSDN Kitaplığı

Windows Geliştirme Win32 API SDK Dokümantasyon Referansı

Referans bölümünde, gelecek uzantılardan birini gösteren işlevlerin açıklamalarına göz atabilirsiniz:

Eksen, MSDN'de API işlevi hakkında da bilgi bulunan bir adrestir:

MSDN Kitaplığı

Kullanıcı Arayüzü Tasarımı ve Geliştirme SDK Belgeleri Windows Kabuğu

Adım atan bebekte, MSDN geliştirme sisteminin penceresinin bir parçası gösterilir:

Eksen, örneğin MSDN'de CopyRect işleviyle açıklanmıştır:

KopyalaRect

bu KopyalaRect bir dikdörtgenin fonksiyon koordinatlarını diğerine kopyalayın.

BOOL CopyRect(
LPRECT lprcDst, // hedef dikdörtgen
İNŞAAT REKT* lprcSrc// kaynak dikdörtgen
);

parametreler

lprcDst
işaretçisi REKT Varsayılanın yapısı, kaynak dikdörtgenin mantıksal koordinatlarıdır.
lprcSrc
Mantıksal gruplar halinde kopyalama için koordinatlar gibi RECT yapılarına yönelik işaretçi.

Dönüş Değerleri

Vicon'un bir fonksiyonu olarak, değerin dönüşü sıfır değildir.
İşlev başarısız olduğu gibi, dönüş değeri sıfırdır.
Windows NT/2000/XP: Ek hata bilgilerini almak için GetLastError'u arayın.

Notlar

Özelleştirme parçaları, çeşitli amaçlar için dikdörtgenleri işaretleyebilir, dikdörtgen işlevleri, kesin ölçü birimini işaretlemez. Bunun yerine, tüm dikdörtgen koordinatları ve boyutları işaretli, mantıksal değerlerle verilir. Eşleme modu ve işlevi bazı dikdörtgen değerlerde ölçü birimleridir.

Örnek Kod

Bir örnek için bkz. Dikdörtgenleri Kullanma.

Gereksinimler

Windows NT/2000/XP: Windows NT 3.1 ve sonraki sürümlerde bulunur.
Windows 95/98/Me: Windows 95 ve sonraki sürümlerde bulunur.
Başlık: Winuser.h'de bildirildi; Windows.h'yi içerir.
Kitaplık: User32.lib'i kullanın.

Yak bachite, bilgi sonuna kadar bitecek. İşlev, değerleri iki parametre iletilen BOOL türüne dönüştürür: LPRECT ve CONST RECT* yazın - RECT türünde bir yapı üzerindeki göstergeler. Visual FoxPro işlevi belirtildiğinde, ilk parametrenin istek olarak ve diğerinin bir değer olarak iletildiğini belirtmek sizin sorumluluğunuzdadır:

Uzun CopyRect IN User32.dll String @ BİLDİRİM Dst, Sicim kaynak

User32.dll kitaplığında hangi işlevin olduğunu nasıl belirleyebilirim? Biraz basit. Önerilerin yayılmasını sağlayın ( Gereksinimler) paragraf Kitaplığı şunu söyleyin: User32.lib kullanın. Bir yardımcı uzantısı gönderin kitap genişleme dll- ve herşey! Konuşmadan önce orada, Header noktasında, fonksiyonun prototipinin açıklamasının hangi içerme dosyasında yer alması önerilir.

Ve yine de hepsi değil! İşlev yapılarla çalışıyorsa, açıklama RECT yapısına köprülenir. Bu mesajlar için fareye tıklayın, yapının rapor açıklaması ekranda görünecektir.

Visual FoxPro'da Yapı Oluşturma

Visual FoxPro'nun 9. sürümü artık BINTOC ve CTOBIN işlevlerini kullanma özelliğini genişletmiştir. Artık işlevler, sayısal verileri yapılarda özelleştirmeye uygun bir biçime dönüştürmek için ayarlanabilir. BINTOC işlevinin sayıları bir satıra, CTOBIN işlevinin ise satırları bir sayıya dönüştürdüğünü tahmin ediyorum.

BINTOC işlevinin sözdizimi:

BINTOC( nExpression, e-bayrak)

Parametreyi kabul edebilmeniz için üç kullanılabilir değer e-bayrak, ileriye doğru tıngırdatıyoruz:

CTOBIN işlevinin sözdizimi:

CTOBIN(c ifade, e-bayrak)

Olası parametre değerleri e-bayrak:

Aşağıda bu işlevlerin bir özeti verilmiştir:

CTOBIN(BINTOC(1000.55,"4RS"), "4RS") && Sonuç: 1000 ? CTOBIN(BINTOC(-1000.55,"4RS"), "4RS") && Sonuç: -1000 ? CTOBIN(BINTOC(1000.55,"F"), "4N") && Sonuç: 1000.549987929 ? CTOBIN(BINTOC(-1000.55,"F"), "4N") && Sonuç: -1000.549987929 ? CTOBIN(BINTOC(1000.55,"B"), "8N") && Sonuç: 1000.55 ? CTOBIN(BINTOC(-1000.55,"B"), "8N") && Sonuç: -1000.55

Örnek olarak Visual FoxPro değişikliğindeki RECT yapısını yazalım. Bu yapı, dikdörtgen bir alanın koordinatlarını tanımlamak için daha önce gözden geçirilen CopyRect işlevinden tersine çevrilmiştir. Eksen bir yapı olarak MSDN'de açıklanmıştır:

Typedef struct _RECT ( UZUN sol; UZUN üst; UZUN sağ; UZUN alt; ) RECT, *PRECT;

Bachite gibi, RECT yapısı alanları kapsar ve LONG type değeri skin etiketinden alınır. її Visual FoxPro oluşturmak için 16 bayta kadar bir satıra ihtiyacınız vardır.

Aşağıda CopyRect fonksiyonunun seslendirildiği, Dst ve Src yapılarının fonksiyona parametre olarak aktarılması ve daha sonra bir yapının diğerine kopyalanması için oluşturulduğu kod verilmiştir. Uygulama, sayıları bir satıra dönüştürmek için BINTOC işlevine sahiptir:

DECLARE Long CopyRect IN WIN32API String @ Dst, String Src * Form Src yapısı cSrc = BINTOC(nLeft,"4RS") + BINTOC(nTop,"4RS") +; BINTOC(nRight,"4RS") + BINTOC(nBottom,"4RS") * Dst yapısı için alan hazırlayın cDst = REPLICATE(CHR(0),16) nResult = CopyRect(@cDst, cSrc) &&

Üzerine gelinen popo, CTOBIN işlevini kullanarak, її alanlarının sayısal değerlerini çıkararak yapıyı nasıl "çözümleyebileceğinizi" gösterir:

NLeft = CTOBIN(SUBSTR(cDst,1,4), "4RS") && RECT.left nTtop = CTOBIN(SUBSTR(cDst,5,4), "4RS") && RECT.top nRight = CTOBIN(SUBSTR(cDst, 9,4), "4RS") && RECT.sağ nBottom = CTOBIN(SUBSTR(cDst,13,4), "4RS") && RECT.bottom

İşçilerin intikamını alan yapılar

Bir Windows API işlevi, misilleme yapmak için işlev yapısına geçirildiğinde durum genellikle daha da kötüleşir. Örnek olarak, yazıcı üzerinde birbirleri için belge oluşturan StartDoc fonksiyonunu inceleyelim. Eksen її prototipi:

Int StartDoc(HDC hdc, // DC CONST DOCINFO'ya işle* lpdi// dosya adlarını içerir);

Ancak, geçirilen diğer parametre, bir DOCINFO yapısının bir göstergesidir. Eksen yapısı:

Typedef yapısı ( int cbSize; LPCTSTR lpszDocName; LPCTSTR lpszÇıktı; LPCTSTR lpszVeri türü; DWORD fwType; ) DOCINFO, * LPDOCINFO;

İlk yapı alanı, cbSize Geçerli yapının değerini bayt cinsinden alın. Ve üç alan eksene saldırdı - sembolik verilerin intikamını almak için değişime ilişkin bu göstergeler. Zokrema, alan lpszDocName intikam almak gösterge arkadaş olan belgenin adları ile üst üste (belgenin aynı adı, gördüğünüz gibi, belge satırına bakıldığında, arkadaş oldukları).

Visual FoxPro, şovmenlerin intikamını almak için özenle yapılandırılmış bir yapıya sahiptir. İlk olarak, bellek bloğunu görmeniz ve yenisinin göstergesini almanız gerekir. Farklı bir şekilde, Visual FoxPro değişikliğinin değerini bellekte yeniden yazmak gerekir - bu şekilde, gösteri mekanizmasının daha fazla uygulamasına sahip olacağız. Kalan, scho zarobiti - göstergenin değerini yapıya yerleştirin. Kiminle yüz kez viskonlama yapılması gerekiyorsa, şunları yapabiliriz: hafızanın hareket etmekten suçlu olmadığı görülür - aksi takdirde, haracımız boşa gitmeyecek olana kadar göstergemizin bir an için bölgeye işaret edeceği ortaya çıkabilir. bir yıl!

Bellek bloğunu kullanın. "Küçük şeyi" Windows'un derin belleğinden ve görülen işlemin belleğinden (ekiniz için) alabilirsiniz. Başka bir yol daha yüksek hızlı kod olabilir, burada Windows belleği ile çalışmanın en basit yolunu görebiliriz.

GlobalAlloc işlevi, belirtilen boyuttaki bellek bloğunu Windows'tan kaldırır ve göstergeyi yenisine çevirir. Eksen prototip işlevi:

HGLOBAL GlobalAlloc(UINT uFlag'lar, // SIZE_T bellek dağılımının özellikleri dwByte// Bayt olarak genişletin);

Parametre uFlag'lar vyznaє, nasıl anılır. MSDN, aşağıdaki değerlerden birini alabileceğinizi söylüyor:

Aşağıdaki tablodan parametre nedir? uFlag'lar GPTR büküm izi. Ale, nasıl bilebilirim, yak anlamı nedir? GlobalAlloc işlevinin açıklaması ve dağıtım için MSDN'ye bakın. Gereksinimler Bir içerme dosyasının prototipine sahip olup olmadığını merak edin. Bu, Winbase.h dosyasıdır. Bir sonraki adımda aynısı, sabitlerin anlamını açıklar. Eksen, tablo sabitlerinin atandığı dosyanın bir parçasıdır:

/ * Küresel Bellek Bayraklar * / #define GMEM_FIXED 0x0000 #define GMEM_MOVEABLE 0x0002 #define GMEM_NOCOMPACT 0x0010 #define GMEM_NODISCARD 0x0020 #define GMEM_ZEROINIT 0x0040 #define GMEM_MODIFY 0x0080 #define GMEM_DISCARDABLE 0x0100 #define GMEM_NOT_BANKED 0x1000 #define GMEM_SHARE 0x2000 #define GMEM_DDESHARE 0x2000 #define GMEM_NOTIFY 0x4000 #define GMEM_LOWER GMEM_NOT_BANKED #define GMEM_VALID_FLAGS 0x7F72 #define GMEM_INVALID_HANDLE 0x8000 #define GHND (GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_ZEROINIT)

Ayrıca, GPTR = GMEM_FIXED + GMEM_ZEROINIT = 0x0000 + 0x0040 = 0x0040.

Ne tür bir rozmir, vizyonların anası hafıza bloğundan suçludur? Açıkçası, belgenin adının alındığı eşit satır satırı. Basamak poposunda, sesli API işlevleriyle başlayan ve bellek bloğu ile biten aşağıdakileri gösterir:

uFlag'lar, Uzun dwByte cDocumentName = "Kullanılacak belge adı" && Belge adı nLenDocumentName = LEN(cDocumentName) && Satır Uzunluğu hGlobal = GlobalAlloc(GPTR, nLenDocumentName)

Sonraki görev, değiştirilen cDocumentName'i sonraki bellek bloğuna yeniden yazmaktır. Hangisinin hızlandırılması için Visual FoxPro SYS(2600) işlevini kullanın. Eksen її sözdizimi:

SYS(2600, dwAdresi, uzunluk [, cYeniDize])

İşlev, gösterge parametresine bağlı olarak nadasta farklı şekilde gerçekleştirilir. cYeniDize chi ni.

parametre nasıl cYeniDize sipariş edildi, ardından kopyalama işlevi uzunluk değişiklikten bayt cYeniDize belirtilen adresin arkasındaki bilmeceye dwAdresi.

parametre nasıl cYeniDize belirtilmemiş, ardından işlev döner uzunluk belirtilen adres için bellekteki bayt dwAdresi.

Yak bachete, parametre dwAdresi- ce gösterge.

Görülen fonksiyon GlobalAlloc hafızasındaki cDocumentName satırının yerine yazalım:

SYS(2600, hGlobal, nLenDocumentName, cDocumentName)

Eksen, DOCINFO yapısının oluşumu için son koddur:

#DEFINE GPTR 0x0040 DECLARE Long GlobalAlloc IN WIN32API Uzun uFlag'lar, Uzun dwByte cDocumentName = "Kullanılacak belge adı" nLenDocumentName = LEN(cDocumentName) hGlobal = GlobalAlloc(GPTR, nLenDocumentName) SYS(2600, dwAdresi, uzunluk [, cYeniDize]) * DOCINFO yapısını oluşturmaya başlıyor * cDocInfo - değiştirildi, burada cDocInfo = BINTOC(20,"4RS") && DOCINFO oluşturuldu. cbSize cDocInfo = cDocInfo + BINTOC(hGlobal,"4RS") && DOCINFO. lpszDocName cDocInfo = cDocInfo + REPLICATE(CHR(0),12) && Yapının diğer alanları * Yapı oluşumunun sonu

Yapı değişimde oluşur cDocInfo. 20 sayısı ilk chotiri baytına kaydedilir - yapının cerezmir (alan cbSize). Değişikliğe eklenen sonraki birkaç bit, bellek alanının bir göstergesidir, aynı şekilde değişiklik yeniden yazılır cDocumentName - belgenin adı. Ardından, değiştirmeye on iki sıfır bayt daha eklenir - yapının tüm alanları lpszÇıktı, lpszVeri türüі fwType, yakі, zgidno'nun belgeleri göz ardı edilebilir; tse, alanların boş değerlerden kaynaklandığı anlamına gelir. Bu sırayla, bir dizi 20 baytiv dozhinoy - ne anlama geliyordu.

Muzaffer hafızanın özellikleri

Programlarınızda Windows API işlevleri takılıysa, Visual FoxPro'nun bu işlevlerin ne sakladığını hatırlayamadığını hatırlamaktan siz sorumlusunuz. Bunun için, örneğin ek GlobalAlloc işlevi için belleği değiştirirseniz, GlobalFree işlevini çağırarak Windows belleğini çevirmeniz gerekir. API'nin belleği rezerve eden cilt işlevi için, işlev tam tersidir ve ayrılmış bellek yapar.

Eksen prototip işlevi GlobalFree:

HGLOBAL GlobalFree(HGLOBAL hMem // bellek bloğu göstergesi);

İşlev yalnızca bir parametre alır - bellek bloğunun göstergesi. Eksen її Visual FoxPro tarafından seslendirildi:

WIN32API'DE Uzun GlobalFree Bildiri Uzun hGlobal GlobalFree(hGlobal)

Burada hGlobal, GlobalAlloc işlevi tarafından döndürülen bir bellek bloğu göstergesidir.

Hafızanızı tersine çevirmeyi unutursanız, hafıza bobini adı verilen bir soruna takılıp kalma riskiniz vardır. Böyle bir dönüşün sonuçları daha da özetleyici olabilir - programınızın çalışmasında, belleğin parçalanmasından kaynaklanan, işletim sisteminin çökmesine neden olan keskin bir artış olması durumunda.

Dizileri bir işleve geçirmek

Bir bakışta dizi Cі - tse zmіnna, aynı türdeki öğelerin bir çaçasının intikamını almak için scho. Dış görünümle çevrili öğe dizisine erişim, ek bir dizin için ayrılmıştır. Dizinin elemanları aynı rozmіr'a sahip olabilir, diziyi farklı veri türleri ile anlatmak mümkün değildir. Dizinin tüm elemanları, ilk elemana verilen indeksin minimum değeri ve kalanın maksimum değeri ile sırayla, birer birer bellekte saklanır.

Visual FoxPro dizisi, farklı veri türlerinin çeşitli öğelerinde kaydetmenize izin verdiği için farklı şekilde düzenlenebilir. Bu nedenle, bir diziyi Visual FoxPro'dan bir Windows API işlevine yalnızca adını parametre olarak ileterek geçirmek imkansızdır. Ayrıca, DECLARE..DLL komutu bir dizi gibi bu tür verilere sahip değildir.

Kamptan çıkın є. Yapılar gibi, dizilerin transferleri, sembolik değişiklikler galip gelir. Karşılık gelen dizilerden gelen sayısal veriler, Windows API işlevine parametre olarak ilettiğiniz bir satıra dönüştürülür. Bazı nedenlerden dolayı, bir dizide bir satır oluşturan ArrayToString işlevinin kodu. işlev taArray(yardım için) bu sancak tlTypeOfValue; tlTypeOfValue=.F.) veya konuşma ( tlTypeOfValue=.T.) sayılar:

FUNCTION ArrayToString PARAMETRELER taArray, tlTypeOfValue EXTERNAL ARRAY taArray LOCAL lnLenArray, lnIndex, lcStruct, lcType lcType = IIF(tlTypeOfValue = .t., "F", "LncLtl Array"(tlTypeOfValue = .t., "F", "4LncArray") taArray, lcType) ENDFOR RETURN lcStruct ENDFUNC

İşlev, hem tek boyutlu hem de iki boyutlu dizilerle çalışır.

Karakter veri kodlaması: ANSI ve UNICODE biçimleri

ANSI kodlamasında (Visual FoxPro kodlu) bir dış görünüm karakteri bir bayt olarak tanımlanır, bu nedenle maksimum karakter sayısı 256'dır ve bu açıkça çok küçüktür. Örneğin, Ruslaştırma sırasında standart ANSI karakterlerinin bir kısmı Kiril karakterleri ile değiştirilir. Ve bazı alfabelerde, örneğin Japonca kana, sembol stilleri vardır, bu kodlama için bir bayt yeterli değildir. Bu tür mov'ları desteklemek ve daha da önemlisi, programları diğer mov'larla "çevirmeyi" kolaylaştırmak için Unicode kodlaması bölündü. Bir Unicode dış görünüm karakteri, geçerli karakter kümesini 65536'ya kadar genişletmeyi mümkün kılan iki bayttan oluşur.

Unicode biçimindeki karakter dizeleriyle bir saatlik çalışma için dönüştürmek üzere birçok Windows API işlevi eklemek. Bu tür işlevlerle çalışmak için karakter verilerini bir biçimden diğerine dönüştürmek gerekir.

Visual FoxPro STRCONV işlevi, satırları ANSI biçiminden UNICODE'a ve geriye dönüştürmek için tanıtıldı. Eksen її sözdizimi:

STRCONV( cifadesi, nDönüşüm Ayarı [, nRegionalIdentifier [, nRegionalIDType]])

Parametre cifadesi- dönüştürülmesi gereken bir dizi. Parametre nDönüşüm Ayarı dönüşümün doğasını gösterir. Yoganın yardımıyla bizim için sadece iki olası anlam vardır:

  • 5 - ANSI'den UNICODE'a dönüştürme
  • 6 - UNICODE'dan ANSI'ye dönüştürme

Gerekli dil parametreleri nRegionalIdentifierі nRegionalIDType ek bölgesel ayarlamaları ifade eder ve acısız bir şekilde göz ardı edilebilir.

Aşağıda farklı bir STRCONV işlevi örneği verilmiştir:

CUnicodeString = STRCONV(cANSIString, 5) && Unicode'a Dönüştür cANSIString = STRCONV(cUnicodeString, 6) && ANSI'ye Dönüştür

Muhtemelen bu bölümü okuduğunuzda, Visual FoxPro işlevlerini kullanarak Windows API'sine erişmenin kolay olduğu izlenimini edindiniz. І yani і ні. Örneğin, bazı API işlevleri, DECLARE..DLL komutunda desteklenmeyen veri türlerini, örneğin 64 bit tamsayıları içerir. Kapı bekçisinin işlevleri olarak adlandırılan bir dizi işlev de vardır. Böyle bir işlevin prototipi, döndürülecek türün açıklamasından önce bir CALLBACK değiştiricisine sahiptir. Bu tür işlevleri aracı olmadan kazanamıyor olmanız üzücü. Yapının bir işlevi denetlemek için kullanılabileceği de doğrudur - Visual FoxPro'daki bu tür API'ler tek başına yenilemez.

sorumluluk reddi

Geçmişte WinAPI çıksa daha iyi olurdu. Uzun zamandır, çok sayıda çapraz platform çerçevesi var, Windows sadece masaüstlerinde değil, Microsoft'un da muzaffer canavar gibi mağazasında ekleri yok. WinAPI'de nasıl video oluşturulacağına dair birçok makale var, sadece burada değil, tüm İnternet'te, eşit miktarda okul öncesi ve daha fazlası için binlerce olarak sayılırlar. Tüm düzenleme süreci artık atomlar için değil, atom altı parçacıklar içindir. Daha basit ve daha akıllı ne olabilir? Ve buradayım...

Ale, her şey göründüğü kadar basit değil.

Neden şimdi WinAPI hakkında?

Bir keresinde, ahlaksız bir insanda birinin igorunun enkazını çalarken, şöyle düşündüm: Bu böyle bir emülsiyon, ama nalagodzhuvach'ta, normal bir sahip gibi klavyenin düğmelerinde gezinmek gibi basit bir konuşma yoktur.

Ne hakkında konuşuyorum? Ve eksen shmatochku kodu:

Durum WM_KEYDOWN: MessageBox(hwndDlg,"Die!","Öldüm!",MB_YESNO|MB_ICONINFORMATION);
Bu şekilde, yazarlar klavyeye bir dokunuş eklemek istediler ve dahası, Windows zhorstko'daki diyalog pencerelerinin mimarisinin gerçekliği bu tür kendini empoze etmeyi sabitledi. Tі, en azından bilgiyi aldıktan sonra, öykünücüsü ve yenisinin sahibi kimdi?
Sorun ne?

Kanıt şöyle: Böyle çalışamazsın!

Ve WinAPI'nin birincil beslenmesine dönersek: çok popüler ve çok fazla olmasa da projeler kazanmaya devam ediyor ve bu saatte çünkü. Kısacası, saf API'de çok fazla konuşma yapamazsınız (burada her zaman üst düzey dillerin ve montajcının kshtalt'ına analojiler çizebilirsiniz, ancak aynı anda değil). Ama neden olmasın? Sadece göz kırp ve bu kadar.

Problem hakkında

Diyalog pencereleri, robotun GUI ile çalışmasını kolaylaştırırken, aynı zamanda bize bağımsız olarak çalışma yeteneği sağlar. Örneğin, pencere prosedürü için gerekli olan WM_KEYDOWN / WM_KEYUP'ı hatırlatmak, DefDlgProc bindirmelerinde “başlamak”, bu tür kelimelerin adlarını alarak, örneğin: Sekme navigasyonu, Esc, Enter, vb. Ayrıca, diyalogların manuel olarak oluşturulmasına gerek yoktur: basitçe, kaynak düzenleyicide düğmeler, listeler atın, WinMain CreateDialog/DialogBox'a tıklayın ve her şey hazır.

Bu tür önemsiz sorunların üstesinden gelmek kolaydır. Ve en azından iki tamamen yasal yol:

  1. RegisterClassEx aracılığıyla kendi sınıfınızı oluşturun ve WM_KEYDOWN'u sınıf işleme prosedürüne kaydedin, işleme prosedürünü diyaloğun kendisine yönlendirin. Güzel güzel! Kendi sınıfınızla ve VS editörü diyalog için kendi sınıfınızı ayarlamanıza izin verdiğinde diyaloglar oluşturabilirsiniz. Eksen sadece bunu biliyor ve tsim koristuetsya?
    Eksi açıktır: Bir sınıfa kaydolmanız gerekir, 1 CALLBACK prosedürü için anne daha büyüktür, özü paris yayınında daha az olacaktır. Ayrıca, bilmiyoruz kudiїх translyuvati, polis tarafından çitle çevrildim.
  2. Vikoristovuvat vbudovaniya mekhanіzm hızlandırıcıіv. Ve diyalog prosedürünün kodunu değiştiremeyeceğiz! Peki, hey, anahtara / kasaya bir satır ekleyin, ancak aşağıdaki fiyat hakkında.

öğreticiler?

bunu söylemekten korkmuyorum bıyık WinAPI aracılığıyla pencere oluşturmaya yönelik öğreticiler, "onarım işleme döngüsü" gibi basit bir koddan başlar (pencere sınıfını ve diğer bağlamayı hazırlama ayrıntılarını atlayacağım):

while (GetMessage(&msg, nullptr, 0, 0))) ( TranslateMessage(&msg); DispatchMessage(&msg); )
Burada her şey gerçekten basit:

  1. GetMessage() kilit an: Potik'i bloke etmek, boş bir çanta gibi.
  2. WM_KEYDOWN/WM_KEYUP ile TranslateMessage(), WM_CHAR/WM_SYSCHAR uyarısını oluşturur (kendi metin düzenleyicinizi almak istiyorsanız buna ihtiyacınız olacaktır).
  3. DispatchMessage(), pencere prosedürü için bildirimleri (olduğu gibi) yönetir.
Bu kodu hacklemenin güvenli olmadığı gerçeğine bir göz atalım ve bu yüzden. Şaraba saygı gösterin:
Dönüş değeri sıfırdan farklı, sıfır veya -1 olabileceğinden, aşağıdaki gibi kodlardan kaçının:
while (GetMessage(lpMsg, hWnd, 0, 0)) ...
І doğru döngünün poposunu indirin.

Warto, Win32 için VS şablonlarının bunun gibi ek yazımlara sahip olduğunu söylüyor yanlışÇevrim. Çok belirsiz. Adje, a priori doğru olsa bile, yazarların kendilerinin yarattıklarını çok az insan anlıyor. Ve yanlış kod, anlaşılması daha da kolay olan hatalardan bir kerede çarpılır.

Kodun bir sonraki parçası, kural olarak, hızlandırıcıların açıklamasını takip eder ve birkaç yeni satır eklenir (MSDN'deki saygı nedeniyle, doğru döngüyü yazmaya teşvik eder):

HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0))) ( if (-1 == bRet) break; if (!TranslateAccelerator(msg.hwnd, hAccel, &msg)) ( TranslateMessage(&msg); DispatchMes ; ) )
En başarılı seçenek benim. ben ( ta-dam) Yanlış biliyorum!

Değişenler hakkında küçük bir not (hadi bu kodun problemlerinden bahsedelim):

Kaynakların ilk satırına, bir anahtar tablosu eklenir, yak'a basıldığında, WM_COMMAND komut kimliği ile yükseltilir.

Pekala, TranslateAccelerator meşgul: Eğer o anahtar kodu için WM_KEYDOWN'u kontrol etmek istiyorsanız, o listedeyse, o zaman (anahtar anı tekrar edeceğim) WM_COMMAND (MAKEWPARAM (id, 1)) güncelleme argümanlarını oluşturacaksınız, işleme prosedürleri.

İfadenin geri kalanından, sorunun neden ön kodda olduğu anlaşıldı sanırım.
Açıklamama izin verin: GetMessage, “pencere” türündeki TÜM nesneler için tekrar edecek (en fazla içerme ve alt: düğmeler, listeler, vb.) ve TranslateAccelerator oluşturulan WM_COMMAND'i nerede düzeltecek? Bu doğru: geri düğmesi / listesi çok ince. Ale, WM_COMMAND'ı kendi prosedürümüzde işliyoruz, yani onu hesaba katmamız gerekiyor.

TranslateAccelerator'ın oluşturduğumuz pencere için bir çağrıya ihtiyacı olduğu açık:

HWND hMainWnd = CreateWindow(...); HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0))) ( if (-1 == bRet) break; if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) ( TranslateMessage(&msg); DispatchMess;) )
Ve şimdi her şey güzel ve mucizevi: her şeyi ayrıntılı olarak analiz ettik ve her şey mükemmel olabilir.

Biliyorum Hayır. :-) Tse bude pratsyuvati doğru, yeter ki tam olarak bir viknomuz var - bizimki. Modal olmayan yeni bir pencere (diyalog) belirir belirmez, yeni pencereye basılacak olan tüm tuşlar WM_COMMAND'a çevrilecek ve nerede düzeltilecek? Hâlâ doğru olduğunu biliyorum: smutumuz çok eğlenceli.

Bu aşamada, çıkmaz bir durumun sonunda milisleri yaymıyorum, ancak derslerde sanki daha erkenmiş gibi (aksi takdirde müdahale etmiyorlar) konuşmaları yayıyorum.

IsDialogMessage

Bu işlevin adının arkasında benim için ne anlama geldiğini düşünebilirsiniz: diyaloğun bir açıklamasını vermek. Ale, önce ne biliyorsun? Ve farklı bir şekilde, bu bilgilerle ne yaptınız?

Gerçekten, sizi troch'tan soymak için daha fazla, adı alçaltın. Ve kendine:

  • Sekme/Üst Karakter+Sekme/yukarı/aşağı/sağ/sol el kullanarak alt denetimler için gezinme oluşturun. Ayrıca, biz yeterince
  • ESC formuna bastıktan sonra WM_COMMAND(IDCANCEL)
  • WM_COMMAND(IDOK) formunu girin veya kilitten sonra akış düğmesine tıkladıktan sonra
  • Kilitlemeden sonra düğmeleri değiştirme
  • Peki, diyaloglu bir coristuvachev robotunun işini kolaylaştıran başka şeyler de var.
Bize ne veriyorsun? İlk olarak, gün ortasında navigasyon hakkında düşünmemize gerek yok. Biz ve çok bıyıklı zroblyat. Ana penceremize WS_EX_CONTROLPARENT stili eklenerek Sekme gezintisi hızlandırılabilir, ancak temiz ve çok işlevsel değil.

Farklı bir şekilde, listede listelenen diğer tüm noktalarda (ve üç tane daha ekle) hayatı bizim için kolaylaştıracak.

Vzagali, iş güvenliği için burada Windows'un tepesinde galip var kalıcı iletişim pencereleri, Ve modal olmayan diyalogları çağırmak için programcılara verilir. Ancak, zavgodno'da muzaffer olabiliriz:

Bunun da ötesinde, eğer Message Dialog işlevi kutu diyagramı modeline yerleştirilmişse, pencereyi ince ayarlayabilir, işaretleri nasıl işaretleyeceğinizi, pencereleri nasıl düzelteceğinizi, klavyenin kendisini nasıl oluşturacağınızı, iletişim kutusunda nasıl büküleceğini yapabilirsiniz.
Tobto. şimdi, döngüyü şu şekilde biçimlendirebiliriz:

HWND hMainWnd = CreateWindow(...); HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) ( if (!IsDialogMessage(hMainW) TranslateMessage(&msg) ;GöndermeMesajı(&msg); )) )
Yerel bir Windows iletişim kutusu gibi, gezinme yöntemimiz budur. Ve şimdi iki nedolіki aldık:

  1. Bu kod aynı zamanda nazikçe sadece pratik olacaktır. bir (modal olmayan) pencere ile;
  2. Tüm iletişim gezinme seçeneklerini kaldırdıktan sonra, görünüme WM_KEYDOWN/WM_KEYUP uzantısını da ekleyebiliriz (yalnızca pencerenin kendisi için, alt denetimler için değil);
І tüm eğitimlerin hangi aşamada bittiği ve başladığı ekseni: Bir winapi standart iletişim kutusunda klavye olayları nasıl işlenir?
Tse ilk önce kuti'ye gönderildi, ale dönüşü: bin їх. Çözüm önerme hakkında (bunlardan daha kısa - hakkında daha fazla yazdığım, alt sınıflama ve RegisterHotKey'e kendi diyalog sınıfınızı oluşturmak için. Burada "daha kısa" bir yol bulacağım: Windows Hooks kazanmak için).

Öğreticilerde ve incelemelerde olmayanlar hakkında konuşma zamanı geldi.

Kural olarak (kural olarak! Daha fazlasını isteyen varsa, sınıfınızı diyaloglar için kaydedebilir ve bu şekilde pratik yapabilirsiniz. Ve eğer öyleyse, ihtiyacınız olursa bu makaleyi ekleyebilirim) WM_KEYDOWN bağımsız olarak vikni'nin kontrolü altında - tobto. herhangi bir diyalog için hayati bir işlev olarak. Ve eğer öyleyse, WinAPI'nin bizi yaydığı gibi, neden zengin olanaklarla hızlı olmayasınız: Çeviri Hızlandırıcı.

Skrіz vikoristovuyut tam olarak bir hızlandırıcı tablosu ve baş pencereden daha az. Doğruyu söylemek gerekirse: yalnızca bir GetMessage döngüsü döngüsü ve yalnızca bir tablo vardır. Başka nereye gitmeliler?

Aslında GetMessage-loop olabilir yatırımlar. PostQuitMessage açıklamasına tekrar bir göz atalım:

PostQuitMessage, iş parçacığının mesaj kuyruğuna bir WM_QUIT mesajı gönderir ve hemen geri döner;
Mesaj alıyorum:
WM_QUIT mesajını yenilemek için bir fonksiyon olarak, dönüş değeri sıfırdır.
Bu şekilde çıkış prosedüründen PostQuitMessage dediğimiz gibi GetMessage döngüsünden çıkış görünecektir. Bunun anlamı ne?

için yapabiliriz deri modelsiz Kendi benzer döngünüzü oluşturmak için programımızda Vіkna. Bazen DialogBoxParam'a gitmemiz gerekir, çünkü Döngümüzü döndüremiyoruz ve içeri giremiyoruz. Ancak CreateDialogBoxParam veya CreateWindow aracılığıyla bir diyalog oluşturursak, bir döngü döndürebiliriz. tsimu'da deriöyle bir sonuca varır ki diyalog son mesajdan kaynaklanır:

HWND hMainWnd = CreateWindow(...); HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) ( if (!IsDialogMessage(hMainWnd) TranslateMessage(&msg) ; hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), hwnd, MyDialogBoxProc), HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR_FOR_MY_DIALOG)); çünkü iletişim penceresi modal iken (bRet = GetMessage(&msg, 0)) (bRet = GetMessage(&msg, 0)) 1 == bRet) break; if (!TranslateAccelerator(hDlg, hAccel, &msg)) ( if (!isDia , &msg)) ( TranslateMessage(&msg); DispatchMessage(&msg); ) ) ) EnableWindow(hwnd, fSavedEnabledState); / / ana pencereyi etkinleştir.Dialog kapatıldı ara verildi; ) ) INT_PTR CALLBACK MyDlgProc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) ( switch(umsg) ( case WM_CLOSE: ( // EndDialog(hwnd, 0)); - DONT BUNU YAP! // EndDialog YALNIZCA DialogBox(Param) tarafından oluşturulan Modal İletişim Kutuları için geçerlidir DestroyWindow(hwnd); break; ) case WM_DESTROY: ( PostQuitMessage(0); break; ) // .... ) return 0; )
Saygı duyun: şimdi programımızda yeni bir cilt kaplaması için işlemeye ekleyebiliriz vlasnu hızlandırıcı tablo WM_QUIT, GetMessage'ın iletişim döngüsünden çıkmasına izin verir, ancak mevcut döngü bunu yapamaz. Neden bu kadar vіdbuvaetsya?

Sağda, prosedürümüzü çağıran DispatchMessage çağrısında mevcut döngünün “kalkması”, gücünün nasıl açılacağı dahili Aynı DispatchMessage ile GetMessage döngüsü. Klasik arama ekleri (bu DispatchMessage türünde). Bu nedenle, mevcut döngü WM_QUIT'i iptal etmez ve bu aşamayı tamamlamaz. Tüm pratsyuvateme stringko.

Ale ve işte kendi eksikliklerin:
Cilt böyle bir döngü tekrarlanabilir sadece "kendi" penceresi için. Burada diğerlerini bilmiyoruz. Ve bu, burada başka bir döngü belirirse, tüm vicon'ların, TranslateAccelerator/IsDialogMessage çifti ile bildirimlerinin gerekli işlenmesini hesaba katmadığı anlamına gelir.

Eh, tüm saygıyı göstermenin ve programımızın başarısıyla ilgili tüm bilgileri tamamlamak için doğru yolu yazmanın zamanı geldi. Bir akışın ödülünün aşağıda görüldüğüne saygı duymak istiyorum. Çünkü cilt akışı kendi çizgisini yenileyebilir, o zaman cilt akışının kendi yapılarını oluşturması gerekecektir. Koddaki önemsiz değişikliklerle bile mücadele etmek.

Robimo güzel

Çünkü Sorun ifadesi doğruysa ve görevin yarısı ayarlanmışsa, önce görevi doğru şekilde ayarlamam gerekecek.

İlk olarak, mantıklı olurdu, ama sadece daha aktif Her zaman tavsiye kabul ederim. Tobto. etkin olmayan bir pencere için hızlandırıcıları çevirmiyoruz ve IsDialogMessage'a bildirim göndermiyoruz.

Başka bir şekilde, pencere için hızlandırıcılar tablosu ayarlanmamışsa, o zaman hiçbir şey iletilmez, sadece IsDialogMessage'da duyurulur.

Pencere tanımlayıcısını hızlandırıcı tablo tanımlayıcısına eşleyecek basit bir std::map oluşturalım. eksen şöyle:

standart::harita l_mAccelTable;
Ve pencere yaratma dünyasında, favori tablonuza bir tanımlayıcı ile yeni bir pencere ekleyeceğiz (veya böyle bir işlem gerekli olmadığından sıfır).

BOOL AddAccelerators(HWND hWnd, HACCEL hAccel) ( if (IsWindow(hWnd)) ( l_mAccelTable[ hWnd ] = hAccel; DOĞRU döndür; ) YANLIŞ döndür; ) hÖrnek, hız)); ) BOOL AddAccelerators(HWND hWnd, int accel) ( AddAccelerators(hWnd, MAKEINTRESOURCE(accel) döndür);
Bunu ve pencerenin kapanmasından sonra görebilirsiniz. eksen şöyle:

Void DelAccel(HWND hWnd) ( std::map ::iteratör ben = l_mAccelTable.find(hWnd); if (me != l_mAccelTable.end()) ( if (me->saniye) ( DestroyAcceleratorTable(me->saniye); ) l_mAccelTable.erase(me); ) )
Şimdi, yeni bir diyalog/pencere oluşturmak için AddAccelerators(hNewDialog, IDR_MY_ACCEL_TABLE) öğesine tıklayın. Eğri nasıl yapılır: DelAccel(hNewDialog).

Gerekli tanımlayıcılara sahip bir vicon listemiz var. Ana işleme döngümüzde bazı değişiklikler:

// ... HWND hMainWnd = CreateWindow(...); AddAccelerators(hMainWnd, IDR_ACCELERATOR); BOOL bRet = 0; while (bRet = GetMessage(&msg, nullptr, 0, 0))) ( if (-1 == bRet) break; if (!HandleAccelArray(GetActiveWindow(), msg)) ( TranslateMessage(&msg); DispatchMessage ) ) ) // . ..
Çok daha kısa! HandleAccelArray ile ne var ve GetActiveWindow() ile ne var?

Teori Trochy:

Etkin pencerenin tutamacını GetForegroundWindow ve GetActiveWindow döndüren iki işlev vardır. İlki, diğerinin açıklamasında oldukça mantıklı bir şekilde tanımlanmıştır:

Dönüş değeri, çağıran iş parçacığının mesaj kuyruğuna eklenen etkin pencerenin tanıtıcısıdır.Aksi takdirde dönüş değeri NULL'dur.
İlk döner tabla sistemdeki herhangi bir tanımlayıcı ise, gerisi sadece budur, akışımızı hatırlatmak için vikoristovu cherga gibi. Çünkü akışımızın geri kalanı için bizi cıvıldamak için (ve bu, sanki siyahlarımızla ilgilenecekmişsiniz gibi demektir), sonra duracağım.

Yani HandleAccelArray'ın ekseni, onu aktif pencereye bir tanıtıcı olarak geçirirsek, haritamızda aynı pencereyi arar ve hala oradadır, TranslateAccelerator'a yayınlamasını hatırlatırız ve sonra (birincisinin yapması gerekmez) ) IsDialogMessage içinde. Gerisi bildirimi tamamlamadıysa, TranslateMessage/DispatchMessage standart prosedürünü takip etmek için YANLIŞ'ı çevirin.

Şuna benziyor:

BOOL HandleAccelWindow(std::map ::const_iterator mh, MSG & msg) ( const HWND & hWnd = mh->birinci; const HACCEL & hAccel = mh->saniye; if (!TranslateAccelerator(hWnd, hAccel, &msg)) ( // mesaj Translate Try için değil onu IsDialogMessage ile birlikte if (!IsDialogMessage(hWnd, &msg)) ( // yani, varsayılan şeyler FALSE döndürür; ) ) // tamam, mesaj çevrildi.(HWND hActive, MSG & msg) ( if (!hActive) FALSE döndürür; // aktif pencere yok. Yapılacak bir şey yok std::map ::const_iterator mh = l_mAccelTable.find(hActive); if (mh != l_mAccelTable.end()) ( // Anladım! Bu mesajı aktif pencere için çevirmeye çalışın return HandleAccelWindow(mh, msg); ) return FALSE; )
Artık kızımın cildi her zaman en sevdiğim hızlandırıcı tablosunu ekleyebilir ve WM_COMMAND'ı gerekli kodla sakince yakalayıp işleyebilir.

Ve WM_COMMAND kodunda bir satır hakkında başka ne var?

TranslateAccelerator'daki açıklama şunları söylüyor:
Fonksiyonun menüler veya kontroller tarafından gönderilen mesajları gönderdiğini kontrol etmek için, wParam parametresi WM_COMMAND veya WM_SYSCOMMAND mesajının yüksek dereceli kelimesi 1 değerini içerir.
WM_COMMAND işleme kodunu çağırın ve şöyle görünün:

Switch(HIWORD(wParam)) ( case BN_CLICKED // Düğmelerden/menülerden komut ( switch(LOWORD(wParam))) ( case IDC_BUTTON1: DoButton1Stuff(); break; case IDC_BUTTON2: DoButton2Stuff ) break; ) )
Şimdi şöyle yazabilirsiniz:

Switch(HIWORD(wParam)) ( case 1: // hızlandırıcı case BN_CLICKED: // Düğmelerden/menülerden komut ( switch(LOWORD(wParam)) ( case IDC_BUTTON1: DoButton1Stuff(); break; case IDC_BUT) ; // .. .) kırmak; ) )
Ve şimdi, aynı fceux'a dönerek, ekleyerek sadece bir satır Dikkat etmemiz gereken düğme türünden komutları işleme kodunda: klavyeden hata ayıklayıcı. Yeni hızlandırıcı tablosunu VK_KEY => IDC_DEBUGGER_BUTTON ile gerekli özelliklerle güncellemek için kafa döngüsünün etrafına küçük bir sargı eklemek yeterlidir.

Not: Çok az kişi biliyor, ancak kendi hızlandırıcı tablonuzu oluşturabilirsiniz ve şimdi onu hemen durdurabilirsiniz.

P.P.S.: Çünkü Ana döngüyü döndürmek için DialogBox/DialogBoxParam, ardından diyalog onlar aracılığıyla çağrıldığında, hızlandırıcılar çalışmayacak ve döngümüz (veya döngülerimiz) “boşta” olacaktır.

P.P.P.S.: l_mAccelTable kartlarının HandleAccelWindow'una tıkladıktan sonra değişebilir, TranslateAccelerator veya IsDialogMessage, DispatchMessage'ı çağırır ve orada öğreticilerimizde AddAccelerators veya DelAccel'i kullanabilirsiniz! Bu nedenle, işlev yontulmadan sonra yogodan daha iyidir.

Kodu işaretleyebilirsiniz. Standart MS VS 2017 şablonundan oluşturulan kod temel alınmıştır.

Etiketler: Etiketler ekle

Kısaltma API'si, Uygulama Programlama Arayüzü (API), yazılım perakendecilerinin kazanabileceği bir tür hazır işlevler kümesidir. Zagalom tse anlayışı, daha önce sıklıkla alt program kitaplığı olarak adlandırılan şeye eşdeğerdir. Ancak, API'lerin çoğu, bu tür kitaplıkların belirli bir kategorisinden etkilenir.

Geliştirme saatinde, corystuvach'ın sonu için bir katlanır eklenti (MyApplication) almak pratiktir, MyApplication API'si gibi belirli bir programın uygulanması için seçilen bir dizi spesifik dahili fonksiyon oluşturulur. isminde. Diğer programcılar tarafından başka programların oluşturulması için bu işlevlerin etkin bir şekilde değiştirilebildiği sık görülür. Ürünlerini tanıtma stratejisi uygulayan yazarlar ne şekilde beslenme bozukluğundan suçludur - neden doğru coristuvach'lar için bu sete erişim sağlıyorlar? Yazılım paketinin açıklamasında yenisine olumlu bir yanıt varsa, aslında paketin bir dizi API işlevi içerdiğine dair bir ifade var.

Bu şekilde, API'nin çoğu, bir programın parçası olan, ancak aynı zamanda diğer programlarda seçim için uygun olan yazma işlevleri için kullanılabilir. Örneğin, uçtan uca koristuvach için kremsi bir arayüz olan Excel, VB yardımı için programlar oluştururken kullanılabilecek Excel API işlevlerini, zokrema yazabilir.

Açıkçası, Windows API, işletim sisteminin kendisinin bir parçası olan ve aynı zamanda başka herhangi bir program tarafından kullanılabilen bir dizi işlevdir. Bu planda, bir dizi BIOS/DOS sistem kesintisi ile benzerlik tamamen doğrudur, bu aslında DOS API'dir.

Fark, bir yandan Windows API işlevlerinin deposunun, bir yandan DOS'a benzer şekilde önemli ölçüde daha geniş olması, diğer yandan, mevcut olan bilgisayar kaynaklarının doğrudan yönetiminin birçok faydasını içermemesi gerçeğinde yatmaktadır. ön işletim sisteminden programcılara. Ek olarak, Windows API'sine yapılan çağrı, ek prosedürel çağrılar için çağrılır ve DOS çağrıları, Interrupt (“yeniden başlatma”) adı verilen işlemcinin özel bir makine komutu aracılığıyla işlev görür.

Win16 API'si ve Win32 API'si

Görünüşe göre, Windows 3.x'ten Windows 95'e yapılan değişiklik, 16-bit işletim sistemi mimarisinden 32-bit'e geçişi işaret ediyordu. 16 bit Windows API'si (Win16 API) bir gecede yeni bir 32 bit sürüme (Win32 API) değiştirildi. Bu durumda, sadece sokakta bir anneye ihtiyacınız var, küçük bir suçlama için Win32 API, Windows 9x ve Windows NT aileleri için tek olanıdır.

Win API bilgisi ile, kullanımda birçok işlevin olduğu ortaya çıkıyor - en gelişmiş sistem prosedürlerine geçiş gibi başka bir şey değil, yalnızca filmin sözdiziminin uygulanması. Geriye dönüp bakıldığında, farklı bir API ihtiyacı aşağıdaki seçeneklerle tanımlanır:

API işlevleri, gelecekteki işlevler gibi yeni uygulamalar gibi. Tim daha az değildir, bazen ve bu şekilde API zastosuvannya'ya gideceğiz, çünkü bazen üretkenliği artırmaya izin verir (zorema, gündüz saatlerinde iletilen parametrelerin gerekli olmayan değişiklikleri için).

Tanıtılan işlevler, yalnızca sınırlı sayıda farklı API işlevi uygular. Tse dosit basit varyantı.

vzagali'deki çok sayıda API işlevinin mevcut derleyici sürümünde analogları yoktur. Örneğin, VB kullanarak bir dizini silemezsiniz - bunun için DeleteDirectory işlevini kullanmanız gerekir.

Bazı API işlevlerinin (Win API'deki rolleri önemsizdir) düşük hacim sınırı nedeniyle çağrılamaması da önemlidir, örneğin, bellek adresleriyle çalışmak mümkündür. Bir dizi vipadkіv'deki Ale, önemsiz olmayan priyomy programlamaya yardımcı olabilir (zocrema, vipadku z'de aynı adresler).

API kazanіDinamik Bağlantı Kitaplığı (DLL)

Dinamik DLL kitaplıkları olarak Win API uygulamalarının toplanması.

Bu şekilde, gerekli prosedürlere - alt programlara veya fonksiyonlara (yaklaşık olarak projenin ortasında prosedürleri çağırırken olduğu gibi) doğrudan erişim sağlayan iki dinamik kitaplığın geleneksel versiyonunu kullanabiliriz. Bu tür kütüphaneler ek araçlarla oluşturulabilir - VC++, Delphi, Fortran, Assembler.

Çağrı dinamik kitaplıkların dosyaları bir .DLL uzantısına sahip olabilir, ancak bağlayıcı değildir. Win16 için uzantı genellikle takılı kaldı. EXE, harici aygıt sürücülerine .DRV yardımı için atanır.

Kaldırılabilecek Windows API işlevlerinin ve dosyalarının tam sayısını hesaplayın, bunu sorunsuz yapın (her ne kadar sistem kataloğundan pis kokular geliyor olsa da). Bu planda, işletim sisteminin çekirdeğini oluşturacak bir kütüphane deposu, önemli ek işlevlere sahip ana kütüphanelerin deposunu görmek daha olasıdır.

Kitaplıklar Win32 İşletim Çekirdeği API'si Windows sistemleri 95/98:

KERNEL32.DLL: diğer sistem kaynaklarını denetleyen düşük düzeyli bellek bakımı işlevleri;

USER32.DLL: temel olarak çekirdek arayüzün işlevleri şunlardır;

GDI32.DLL: Grafik Aygıt Arayüzü kitaplığı - harici aygıtlarda görüntülenen çeşitli işlevler;

COMDLG32.DLL: genel tanımanın çeşitli diyalog pencereleriyle ilişkili işlevler.

Uzantı işlevlerine sahip ana kütüphaneler:

COMCTL32.DLL: Ağaç Listesi ve Zengin Metin dahil olmak üzere Windows çekirdeğinin bir dizi ek öğesi;

MAPI32.DLL: elektronik posta ile çalışmanın işlevleri;

NETAPI32.DLL: Bir ölçülü çalışmanın bakım unsurları ve işlevleri;

ODBC32.DLL: ODBC protokolü aracılığıyla farklı veritabanlarıyla çalışmak için gereken kitaplık işlevleri;

WINMM.DLL: multimedya sistem işlevlerine erişim işlemleri.

Bu makale, C ++ programlamada yeni başlayanlar gibi, gönüllü olarak veya hatalar uğruna WinAPI yazdılar.
Kendimden geçmek istiyorum:
C++ gurusu olduğumu iddia etmiyorum ama WinAPI.
Sadece merak ediyorum ve WinAPI'nin fonksiyonlarını ve mekanizmalarını geliştirmemi kolaylaştırmak için bu türden birkaç örneği buraya getirmek istiyorum.

Bu yazımda, C++ hakkında bilgi sahibi olmanız gerektiğini, sınıflar oluşturmayı ve onlar için farklı operatörleri değiştirmeyi öğrenmeniz gerektiğini ve zaten sınıfta kendi mekanizmalarınız gibi “kutsal” olduğunuzu kabul ediyorum.

Bu vikoristannya konsolunun oluşturulması

Win32 programlarını kişiselleştirmek için ya da sadece orada nasıl olduğunu merak etmek için, ortadaki her şey konsolda sürekli eziliyormuşum gibi görünüyor.
Bir GUI eklentisi oluşturursanız, ancak bu konsol değilse, konsol bağlı değildir. Eksen kodunu öğrenmek için internete tıklayın

Eğer(AllocConsole())
{



std::ios::sync_with_stdio();
}
Şeffaflık adına, yogoyu bir fonksiyona sarın. Örneğin:
geçersiz CreateConsole()
{
if (AllocConsole())
{
int hCrt = _open_osfhandle((uzun)GetStdHandle(STD_OUTPUT_HANDLE), 4);
*stdout = *(::_fdopen(hCrt, "w"));
::setvbuf(stdout, NULL, _IONBF, 0);
*stderr = *(::_fdopen(hCrt, "w"));
::setvbuf(stderr, NULL, _IONBF, 0);
std::ios::sync_with_stdio();
}

Viklikana konsolu sadece görüntüleme modunda çalışır ve konsol eklentilerinde olduğu gibi çalışır. Bilgileri ses olarak girin - cout / wcout.
Bu kodun uygulanması için projeden önce aşağıdaki dosyaların eklenmesi gerekmektedir:
#Dahil etmek
#include #include
ve genel ad alanı için std ad alanını etkinleştirin:
ad alanı std kullanarak;
Açıkçası, bunu yapmak istemiyorsanız, bildiğiniz tüm varlıklara std:: ekleyin.

Bu aritmileri görmek için düşen nesneler. operasyonlar

Bu vivechenni'yi yarattığınız zaman, "nihayet" beni zavzhd konsola bir miktar değer girmeniz gerekiyor.
Örneğin:
Nesne verilerini kaydetmek için parametrenin RECT yapısının nesnesinin adresine iletildiği GetClientRect ek işlevi için pencerenin istemci alanının boyutunu alırsınız. İstemci alanınızın boyutunu bilmeniz gerekiyorsa, bunu zaten bağlı olan konsola girmeniz yeterlidir.

cout<

Ale çok hızlı çalışıyor (özellikle de genellikle böyle çalışmak zorunda olduğunuz için) kullanışlı değil.
Burada düşüşün yardımına geliyoruz.
RECT yapısına giren bir sınıf oluşturun ve çıktı operatörünü değiştirin<< так, как вам угодно.
Örneğin:

Sınıf newrect:genel RECT
{
halka açık:
arkadaş akışı ve operatörü<<(ostream &strm,newrect &rect)
{
yol<<"Prtint RECT object:\n";
yol<dönüş strm'si;
}
};

Şimdi cout/wcout yardımı için nesneyi girin:

cout<

Ve sana göre, elin görüşünde her şeyi ihtiyacın olduğu gibi görürsün.
Ayrıca, ihtiyacınız olan herhangi bir operatörle çalışabilirsiniz.
Örneğin, yapıları değiştirmeniz veya çekmeniz gerekiyorsa (örneğin, aynı RECT veya POINT) - operatör==() ve operatör=()'i uygun şekilde değiştirin.
Daha az operatör uygulamak istiyorsanız< что бы быстро сравнивать размеры окна и т.д. перегрузите operator<().
Bu yüzden, kabul ediyorum, belki bazı yapılarla ve daha kafalı olarak, RECT yapısının en büyük nesnesi ile çalışan tüm fonksiyonlar, bu yüzden onunla çalışmak iyi olacaktır.
Ayrıca tüm güzelliği bağlı olan bir okremium dosyasına koymanızı ve gerekirse ince ayar yapmanızı öneririm.

Senin sınıfın

Başkaları nasıl bilmiyorum ama yeşillikleri biliyorum, cilt işlevi için yazdım ya da cilt kafa / kitap başlığının altına yeni bir proje oluşturmak için her şeyin açıkta yapıldığını ve arkamı dönebildiğimi ve bir noktada yati gerekli anlarda hafızamı tazele.
Bu yüzden WinAPI'de en basit pencereyi oluşturmak için sınıf yapısını yüklemeniz, kaydetmeniz ve önemsiz bir pencere prosedürü yazmanız gerekiyor, sanırım hala C++ ile yazdığım üçüncü veya dördüncü projeden sonra.
Sonuç olarak, her şeyi basit bir sınıfta topluyorum. Pencere tutamacı, ad, sınıf adı, pencere prosedür adresleri, pencere sınıfı (WNDCLASS) tümü sınıfın özel bölümünde kilitlenir.
їх otrimannya için basit bir yöntem-Get "eri tanımlayın, örneğin:
HWND GetHWND()
LPCTSTR GetClsName() vb.
Pencere sınıfının kaydı, pencerenin kendisinin oluşturulması ve gösteri tasarımcıda gerçekleştirilir.
Anlaşılır olması için, yapıcıyı değiştirebilir ve simge sınıfının bu kaydını, sınıfın özel bir işlevi ve dış görünüm oluşturucusunun çağrılabilirliği olarak kaydedebilirsiniz. Değişikliğin çok yönlülüğü, bazen basit bir tasarım yaratmam gerekmesi ve yapıcıyı iki parametre ile çağırmam gerçeğine dayanıyor - pencerenin adı ve örnek program.
Aynı zamanda, varsayılan pencere prosedürüyle değil, farklı bir şarkı stiliyle özel boyutlara sahip bir pencere oluşturmak daha az gerekli - yapıcıyı ek parametrelerle çağırıyorum.
Bu sınıf, IDE'nin içerme klasöründe bulunan okremo bağlantılı dosyada bana atanmıştır.
Bu sınıfın şablonu:
sınıf BaseWindow
{
WNDCLASSEX_wcex;
TCHAR_className;
TCHAR_pencereAdı;
HWND_hwnd;
bool_WindowCreation();
halka açık:
BaseWindow(LPCTSTR pencereAdı,HINSTANCE hInstance,DWORD stili,UINT x,UINT y,UINT yüksekliği,UINT genişliği);
BaseWindow(LPCTSTR pencereAdı, HINSTANCE hInstance);
const HWND GetHWND() const(dönüş HWND;)
LPCTSTR GetWndName()const(dönüş _windowName;)
};

İyi düşünüp böyle bir ders yazdıktan sonra, hayatınızı kolaylaştıracak ve aynı şeyi yazmanın temellerini öğrenmek ve geliştirmek için daha fazla zaman harcayacaksınız. Tim daha büyük, buna daha çok saygı duyuyorum - böyle bir dersi kendim öğrenmek ve gerektiğinde yoga eklemek.

not

Açıklanan her şey şunlar için geçerlidir:
Platform – Windows 7 32 bit
IDE - Visual Studio 2010
Belki bir başkası için, kahkaha ve ironi haykırmak için, ama yine de hepimiz yeni gelenler / stajyerler / gençlerdik.
Gönderiden önce kendinizi rozumіnyam'a koymanızı rica ediyorum. Yapıcı eleştiri, elbette, vitaetsya. Sabit diskler