Temel Windows hizmetleri ve API işlevleri. Windows API - bir dizi işletim sistemi işlevi. Neden şimdi WinAPI?

Hadi! Hadi! Bugün nihayet Windows penceresini yeniden açıyoruz. Elveda zavallı konsol!

O zamana kadar C++ sözdizimine aşina olmanız, döngülerin ve döngülerin nasıl kullanılacağını anlamanız ve işlevlerin nasıl iyi çalıştığını anlamanız gerekir. Eğer bir deniz savaşında yakalandıysanız, yakaladıklarınızı not edebilirsiniz.

Ugorsk kayıt formu

WinAPI tarafından kullanılan tüm kodlar Ukraynaca biçimde yazılmıştır. Kodu iyi yazmak iyi bir fikirdir.

Değişikliğin adının önüne kimin koçanı harfi yerleştirilmelidir? Önemli işlevlerin adlarındaki tüm kelimeler büyük harfle başlar.

Öneklerin ekseni:

b – bool türünü değiştirin.
l - uzun tamsayı türünü değiştirin.
w – kelime (kelime) – 16 bit. İmzasız kısa türün adı.
dw – çift kelime (alt kelime) – 32 bit. Zminna tipi imzasız uzun.
sz - sıfırla biten bir satır (dize sıfırla sonlandırıldı). Sürekli olarak vikorize ettiğimiz basit bir satır.
p veya lp – işaretçi. lp (uzun işaretçi olarak) – bu göstergeler geçmişten aktarılmıştır. Aynı zamanda lp i p aynı anlama gelir.
h – açıklama (tür tanıtıcısı).

Örneğin eksen şu şekilde çağrılır:

geçersiz * pVeri;

Bu giriş formunun telif hakkı Microsoft'a aittir. Değişkenlerin isimlendirilmesinde kullanılan bu yöntemi eleştiren pek çok kişi var. Ancak benzer konuşmalar (özellikle kodlamayla ilgili) büyük şirketler için hayati önem taşıyor.

Sabit tanımlayıcıların büyük harflere dayandığını hatırlatmak isterim: WM_DESTROY. WM_DESTOY - değer 2, sabit tanımlama yoluyla tanımlanır.

Ek olarak, winAPI'de birçok yeniden atama türü vardır. Bu sayfadaki eksen http://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx'tir, tüm Windows türlerinin açıklamalarını (İngilizce) bulabilirsiniz.

Ve anlamadığımız bir konuşma daha. Duşlara genellikle NULL değerleri verilir. Lütfen bunun yalnızca 0 olduğunu ve NULL (sıfır) değeri atanan imzalayanların bir bellek paylaşımını belirtmediklerini unutmayın.

Windows API'si (WinAPI)

Tüm Windows programları özel bir programlama arayüzü olan WinAPI'yi kullanır. Movi C'deki işlevler ve yapılar dizisi, programınızın Windows'ta iyi çalışmasını sağlar.

Windows API, işletim sistemiyle çalışmak için mükemmel yeteneklere sahiptir. Sınırsız diyebilirsiniz.

WinAPI'nin sadece yüz yeteneğine bakamayız. Şu anda daha fazla materyal almak istiyorum, ancak bu çok zaman alır ve WinAPI'yi bataklıklara indirdikten sonra birkaç kayada DirectX'e ulaşırız. WinAPI'nin açıklaması, iki ders alacağız (bu dahil). Sadece programın çerçevesine bakacaklar.

Windows için bir program, tıpkı DOS için bir program gibi, ana işleve sahiptir. Burada bu fonksiyona WinMain denir.

WinMain işlevi

Bir Windows programı aşağıdaki parçalardan oluşur (her şey WinMain'de saklanır):

Sınıf penceresinin oluşturulması ve kaydedilmesi. C++ sınıflarıyla karıştırmayın. WinAPI C dilinde yazılmıştır, ortak bir kelime olarak bize tanıdık gelen birçok sınıf vardır.
Program penceresinin oluşturulması.
Bilginin oluştuğu ana döngü.
İşleme son prosedürde raporlanır. Pencere prosedürü birincil bir fonksiyondur.
Eksen ve birkaç nokta Windows programlarının temelini oluşturur. Bu yeni dersi genişleterek her şeyi detaylı bir şekilde çözeceğiz. Programların açıklamalarında kaybolursanız bu noktalara geri dönün.

Şimdi hepsini sıralayalım:

WinAPI: WNDCLASS yapısı

Öncelikle WNDCLASS yapısal değişikliğini oluşturup kaydetmemiz ve ardından buna dayalı son sınıfı kaydetmemiz gerekiyor.

Eksen şu yapıya benzer:

c++ kodum typedef struct ( UINT stili; // pencere stili WNDPROC lpfnWndProc; // pencere prosedürü göstergesi int cbClsExtra; // sınıftan sonraki ek baytlar. İlk önce 0'a ayarlayın int cbWndExtra; // pencere örneğinden sonra ek baytlar. İlk olarak şuna ayarlayın: 0 / program programı: WinMain HICON hIcon'daki görünüm parametresi tarafından iletildi; // program simgesi HCURSOR hCursor; // program imleci HBRUSH hbrBackground; arka plan rengi LPCTSTR lpszMenuName;

WinAPI deposundaki WNDCLASS yapısı, oluşturulan pencerenin temel güçlerini tanımlar: simgeler, fare imleci görünümü, pencerenin menüsü, pencerede hangi eklentinin olacağı...

Bu yapıyı kaydettikten sonra son sınıfı bu temelde kaydedebilirsiniz. C++ ile aynı sınıflar yoktur. Artık bunun sisteme kaydettiğiniz şablon olduğunu hatırlayabilir ve artık bu şablonu temel alarak yeni bir şablon oluşturabilirsiniz. Ve WNDCLASS'in yapısal değişikliğinden öğrendiğiniz gibi, tüm bu günler yetkililer tarafından yönetilecek.

WinAPI: CreateWindow işlevi

Yeni sınıfı kaydettikten sonra ana programlar buna göre oluşturulur (başka bir noktaya geçtik). Bu ek işlevi CreateWindow'u deneyin. Saldırgan bir prototip olabilir:

c++ kodum HWND CreateWindow(LPCTSTR lpClassName // sınıf adı LPCTSTR lpWindowName // pencere adı (başlıkta görüntülenir) DWORD dwStyle // pencere stili int x // ekranın sol kenarından yatay koordinat int y // dikey koordinat wow kenar ekranı int nWidth, // pencere genişliği int nHeight, // pencere yüksekliği HWND hWndParent, // babanın penceresi HMENU hMenu, // menü açıklaması HINSTANCE hInstance, // program örneği LPVOID lpParam // parametre ilk olarak NULL olarak ayarlandı);

Pencere sınıfına (WNDCLASS yapısı) pencerenin temel yetkileri verildiğinden, burada belirli dış görünüm penceresi parametreleri verilmiştir: pencere boyutu, koordinatlar...

Bu işlev açıklama penceresini döndürür. Daha fazla açıklama için tanımlayıcıya benzeyen pencereye gidebilirsiniz.

Lütfen burada birçok yeni türün bulunduğunu unutmayın. Aslında tüm koku eskidir, yeni adlandırılmıştır. Örneğin: HWND, HANDLE türüne bir yeniden atama değildir; bu, kendi açısından PVOID'ye yeniden atamadır ve bu aynı zamanda void*'e ​​yeniden atamadır. Gerçek o kadar derinde gömülü ki! Sonuçta HWND tipi bir boşluk işareti değildir.

Pencere birçok parçadan oluşur. Aslında her programda şunları göreceksiniz: pencerenin başlığı, sistem menüsü (pencerenin sol üst kısmındaki program simgesine tıklayın), pencereyle çalışmak için üç sistem düğmesi: ışığı aç, tam ekran ve kapalı. Ayrıca hemen hemen her zaman ek olarak bir menü vardır. Geriye kalanın ekseni kesinlikle bizde olmayacak. Ve elbette, pencerenin çoğu sözde tarafından işgal ediliyor. müşterinin çalıştığı müşteri alanı.

Bu, pencere rejiminden daha iyidir. Uzun süre DiectX ile pratik yapmaya devam edersek tam ekran modunu kullanmayacağız.

Mesaj işleme

Windows altındaki tüm gelişmiş programların temel yararı, güncellemelerin işlenmesidir.

Örneğin, bir kullanıcı klavyede bir tuşa bastığında, bir tuşa basıldığına dair bir bildirim oluşturulur. Daha sonra tuşa bastığınızda aktif olan programın farkında olmanız gerekir.

Burada bir olayımız var; bir tuşa basıldı.

Eylemler şunlar olabilir: fare imlecini hareket ettirmek, programların odağını değiştirmek, klavye tuşlarına basmak, pencereyi kapatmak. Oldukça zengin. Duje! İşletim sisteminde bir saniyede onlarca mesaj oluşturulabiliyor.

Yani herhangi bir yanıt olması durumunda işletim sistemi bir bildirim oluşturur: tuşa basıldığında fare imlecinin koordinatları değişir ve yeni bir pencere açılır.

Bilgi hem işletim sistemi hem de çeşitli programlar tarafından oluşturulabilir.

Yaklaşan siparişin yapısı ve görünümü:

c++ kodum typedef struct tagMSG ( HWND hwnd; // bildirim UINT mesajını gösteren pencere; // bildirim kodu WPARAM wParam; // parametre LPARAM lParam; // parametre DWORD zamanı; // bildirimin yayınlandığı saat POINT pt; // fare imlecini koordine eder) MSG;

Lütfen yapıların typedef'ler kullanılarak yeniden atandığına dikkat edin.

Bu yapıyı oluşturmak için aşağıdaki kodu hızlı bir şekilde kullanabilirsiniz:

c++ kodum msg.messgae == 2; // bunlar iki satır eşdeğer parçadır msg.message == WM_DESTROY; // sabit WM_DESTROY eski iki

İşte bildirim kodunun bulunduğu alandır (bildirim adı WM_DESTROY sabitine eşittir. WM - Windows Mesajında ​​(Windows alt sistemi). WM_DESTROY - pencere kapatıldığında oluşturulan bildirimdir (yok - kaydet) ).

Kodlar ek sabitlerin ve WM_ önekinin arkasında gösterilir: WM_CLOSE, WM_CREATE ve diğerleri.

MSG yapısının HWND tipi - Pencere Tutacağı (pencere tanıtıcısı ve pencere açıklaması) vardır. Bu dünyayı tanımlayan türden bir şey. Fiyat ID sembolü (pencere adı) içindir.

Bu kelimeyi hatırlayın - tanıtıcı (açıklayın, tanımlayıcı). Windows'ta bu çok yaygın bir kötüye kullanım konusudur. Ayrıca H ile başlayan tüm Windows türleri açıklamalardır: simge açıklaması, yazı tipi açıklaması, program örneği açıklaması. Hatırladığım kadarıyla otuz kadar var.

Windows'taki uygulamalar arasındaki tüm etkileşimler bu pencere açıklamaları (HWND'ler) kullanılarak gerçekleşir.

Başka bir önemli tanımlayıcı daha var - program tanımlayıcı (HINSTANCE - WinMain'in ilk parametresi) - bu benzersiz bir program tanımlayıcısıdır, çünkü herhangi bir işletim sistemi iki farklı programı karıştıramaz. Bu yaklaşık olarak bir barkod gibidir. Buna daha sonra bakacağız.

Herhangi bir eylemi gerçekleştirdiğinizde hemen bir bildirim oluşturulur ve hatırlanır: bildirimi iptal edebileceğiniz bir açıklama penceresi ayarlanır, bildirim kimliği ayarlanır, parametreler kaydedilir, siparişin saati (geçerli) kaydedilir Koordinatları bulun fare imlecinin (yapıya bakın).

Bu bildirimden sonra işletim sisteminin bir sonraki bildirimine geçin. Bilgilerimize gelince gerekli pencereye gönderilecektir (Windows, cilt bilgilerini uzmanlara nasıl göndereceğini bilir). Programlardan haberdarsanız, programlar hakkında bilgi sahibi olmanız gerekecektir. Dibe inmek zor, sıkıcı oluyor.

Şu anda, kullanıcı herhangi bir eylem gerçekleştirdiğinde (mesaj görüntülendi ve bir mesaj oluşturuldu) ve program bu eyleme tepki verdiğinde (mesaj program tarafından oluşturuldu), çok fazla şeyin olması şaşırtıcı. bilginin. Windows kullanıyor olsanız bile programlardan da birçok bilgi alabilirsiniz. İlkinde yüzlerce, diğerinde ise en azından birkaç tane olabilir.

Pencere prosedürü - WndProc

Bilgilerin harcandığı andan programın sonuna kadar devam ediyoruz. Çok uzun zaman oldu ve parçalanmaya başlıyor. İşleme için lütfen dış görünüm programının özel bir işlevi olduğunu unutmayın - bir pencere prosedürü. Buna WndProc (Pencere Prosedüründen) adı verilir. Genişletme prosedürünün penceresi ana program döngüsünde yürütülür ve döngünün her yinelemesinde tamamlanır.

Bilgiler (MSG'deki yapısal değişiklikler biçiminde) bu işleve parametreler biçiminde uygulanır: pencere açıklaması, bildirim tanımlayıcı ve iki parametre. Lütfen time ve pt alanlarının pencere prosedürüne aktarılmadığını unutmayın. Totto, sana söyleyeyim, bu zaten "rozіbran".

Pencere prosedürünün ortasında, bildirim kimliğinin kontrol edilmesini içeren anahtar kaldırılır. Eksen, basit bir pencere prosedürünün bir örneğidir (tamamen çalışıyor):

c++ kodum// HRESULT ve __stdcall ile zamanınızı boşa harcamayın. Onlara daha sonra bakacağız. ) // derleyici bilgilendirmeye karar verir)

Ben kalıyorum – ana döngü. Vin daha da basittir. Döngünün her yinelemesi program tarafından doğrulanır. Bilgiye sahip olduğunuz anda ona çekilirsiniz. Daha sonra döngüden bilgiyi işlemek için pencere prosedürüne tıklaması istenecektir.

Eksen tüm hızıyla devam ediyor ve her şey bugün için. WinAPI altındaki bir programın DOS altındaki bir programa çok daha fazla benzediği zaten açıktır. Daha önce de yazdığım gibi önümüzdeki derste çalışan programın koduna bakacağız.

Yeni bir proje oluşturma hakkım var. Yeni Proje penceresinde bir şablon seçin – Win32Project (daha önce Win32 Konsol Uygulamasını seçmiştik). Gelecek pencerelerden birinde Boş Proje bayrağını ayarlamayın; IDE hazırlanmış bir program oluşturacaktır.

project_name.cpp dosyasındaki koda dikkatlice bakarsanız, tartıştığımız her şeyi göreceksiniz: MSG'nin yapısal değişikliği, WNDCLASS yapısının doldurulması, CreateWindow işlevi tarafından bir pencere oluşturulması, ana program döngüsü . Ayrıca dosyaya WndProc işlevi atanır. Anahtar kutularında bir dizi bilgiyi işlemeniz gerekir: WM_COMMAND, WM_PAINT, WM_DESTROY. Dosyadaki her şeyi bulun.

Programda gördüklerimize ek olarak birçok ek kod bulunmaktadır. Bir sonraki sürümde program koduna bakacağız, böylece her şey doğrulanacak. IDE'nin ürettiğinden çok daha basit ve daha akıllı olacak.

Sorumluluk reddi beyanı

WinAPI'nin hemen yan tarafta çıkacağını düşünürdüm. Çok sayıda platformlar arası çerçevenin olduğu, Windows'un yalnızca masaüstü bilgisayarlarda olmadığı ve Microsoft'un kendi mağazasında bu canavarı haklı çıkaracak eklentiler eklemekten çekinmediği uzun zamandır açıktı. WinAPI'de nasıl yaratılacağına dair sadece burada değil, İnternet'te de binlerce makale var; sayıları hem okul öncesi hem de ötesinde binlerce. Tüm parçalama süreci artık atomlara değil, atom altı parçacıklara dayanıyor. Daha basit ve daha akıllı ne olabilir? Ve buradayım...

Ancak her şey göründüğü kadar basit değildir.

Neden şimdi WinAPI?

Bir gün, aynı güzel şeyden yorulmuşken şöyle düşündüm: Bu da ne böyle ve editörde, herhangi bir normal editörde olduğu gibi klavye tuşları arasında gezinmek kadar basit bir dil yok.

Neden bahsediyorum? Ve aks kodu:

Vaka WM_KEYDOWN:MessageBox(hwndDlg,"Öl!","Öldüm!",MB_YESNO|MB_ICONINFORMATION);
Yazarlar bu şekilde klavyeye destek eklemek istediler, ancak Windows'taki iletişim pencerelerinin mimarisinin gerçekliği, bu tür bir zevke düşkünlüğü ciddi şekilde cezalandırdı. Emülatör veya denetleyici kullanmış olan var mı, bunu bilmek ister misiniz?
Sorun ne?

Cevap şu: bu şekilde çalışamazsınız!

Ve WinAPI'nin koçanı beslemesine geri dönelim: Şu anda bunu vikorize etmeye devam edecek çok fazla popüler proje var ve çok fazla değil, çünkü Kısacası, saf API üzerinde çok fazla konuşma yapamazsınız (burada, yüksek kaliteli dil ve montajcının seviyelendirilmesine sonsuz analojiler çizebilirsiniz, ancak hiç de değil). Neden? Sadece vikorist ve bu kadar.

Problem hakkında

İletişim pencereleriyle çalışmak GUI'ye göre daha kolaydır, aynı zamanda bize işleri kendi başımıza yapma fırsatı verir. Örneğin, pencere prosedüründe bulunan WM_KEYDOWN/WM_KEYUP bilgisi DefDlgProc alt bölümlerinde bulunur ve aşağıdaki gibi sözcükler içerir: Sekmede gezinme, Esc'nin işlenmesi, Enter tuşları vb. Ayrıca, diyalogları manuel olarak oluşturmanıza gerek yoktur: sadece düğmeler, listeler, kaynak düzenleyici ekleyin, WinMain CreateDialog/DialogBox'a tıklayın ve işiniz bitti.

Bu tür diğer sırları aşmak kolaydır. Ve en azından tamamen yasal iki yol:

  1. RegisterClassEx aracılığıyla kendi sınıfınızı oluşturun ve sınıf işleme prosedürüne WM_KEYDOWN ekleyin ve onu diyalog işleme prosedürünün kendisine yönlendirin. Şöyle böyle! Kendi sınıfınızla diyaloglar oluşturabilir ve diyalog için sınıfa bir ad belirlemenize olanak tanıyan VS düzenleyicisini kullanabilirsiniz. Bunu bilen ve kendi kendine hizmet eden var mı?
    Bariz dezavantaj: Bir sınıfa daha kaydolmak gerekir, bu nedenle 1 CALLBACK prosedürü daha vardır, bunun özü bahis yayınında kaybolacaktır. Üstelik bilmiyoruz kudi Bunlar ihlal edilecek ve polis tetikte olacak.
  2. Vikoristovat hızlandırıcı mekanizmasının uygulanması. Ve hiçbir zaman diyalog prosedürünün kodunu değiştirmek zorunda kalmayacağız! Peki neden anahtara / kasaya bir satır eklemiyorsunuz, ancak fiyat daha düşük.

Öğreticiler?

bunu söylemekten korkmuyorum Bıyık WinAPI aracılığıyla pencere oluşturmaya yönelik öğreticiler, işlem döngüsünün nasıl raporlandığını gösteren basit bir kodla başlar (Pencere sınıfının ve diğer bağlantıların hazırlanmasına ilişkin ayrıntıları atlayacağım):

While (GetMessage(&msg, nullptr, 0, 0)) ( TranslateMessage(&msg); DispatchMessage(&msg); )
Burada gerçekten çok basit:

  1. GetMessage() şeytanın mesajını haykırıyor ve kilit nokta: Boş olduğu için akışı engeller
  2. WM_KEYDOWN/WM_KEYUP ile TranslateMessage(), WM_CHAR/WM_SYSCHAR bildirimini oluşturur (kendi metin düzenleyicinizi oluşturmak istiyorsanız bu gereklidir).
  3. DispatchMessage(), bildirimi pencere prosedürüne (olduğu gibi) gönderir.
Bu kodu vikorize etmenin güvenli olmadığı açıktır ve bu yüzden. Saygıyı yeniden şaraba dönüştürün:
Bu nedenle, dönüş değeri sıfırdan farklı, sıfır veya -1 olabilir; aşağıdaki gibi kodlardan kaçının:
while (GetMessage(lpMsg, hWnd, 0, 0)) ...
І doğru döngüde popoyu daha aşağıya doğru hedefleyin.

Varto, Win32 için VS şablonlarının aynı yazım eklemelerine sahip olduğunu söyledi yanlış döngü. Ve bu gerçekten çılgınca. Her ne kadar çok az kişi yazarların kendilerinin derlediklerini araştırsa da, bu a priori doğrudur. Ve yanlış kod, yakalanması çok zor olan hatalarla çoğalır.

Bu kod parçasından sonra, kural olarak, hızlandırıcılar hakkında bir tartışma yapılır ve birkaç yeni satır eklenir (MSDN ile ilgili olarak, doğru döngüyü yazmanızı tavsiye ederim):

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 ; ) )
Bu seçeneği en sık tercih ediyorum. ben kazandım ( ta-baraj) Znovu yanılıyor!

Değişenlerden (ve ardından bu kodla ilgili sorunlardan) bahsedeceğim:

Kaynakların ilk satırında bir anahtar tablosu seçilir ve formatlardan herhangi birine tıkladığınızda, karşılık gelen komut kimliğiyle birlikte WM_COMMAND bildirimi görüntülenecektir.

TranslateAccelerator'ın yaptığı budur: WM_KEYDOWN ve bu listedeki anahtar kodu nasıl alınır, ardından (yine anahtar nokta) WM_COMMAND (MAKEWPARAM(id, 1)) mesajını biçimlendirin ve türlere gönderin Pencere için bir gün İlk argümanda belirtilen tanıtıcı, işleme prosedürleri.

Geriye kalan ifadeyle sanırım önceki koddaki sorunun ne olduğu anlaşıldı.
Açıklamama izin verin: GetMessage, "pencere" türündeki TÜM nesneler için seçilir (çocuklar dahil: düğmeler, listeler vb.) ve TranslateAccelerator, oluşturulan WM_COMMAND'ı nereye gönderir? Doğru: düğmeye/listeye geri dön. Prosedürümüze WM_COMMAND'ı ekliyoruz, bu da onu kaldırmamız gerektiği anlamına geliyor.

Oluşturduğumuz pencere için TranslateAccelerator'ın kullanılması gerektiği ortaya çıktı:

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 )
Artık her şey yolunda ve harika: Her şeyi ayrıntılarıyla hallettik ve her şey mükemmel çalışıyor.

Tekrar biliyorum. :-) Tek bir şeyimiz olduğu sürece bunu doğru yapalım: bizimki. Modal olmayan yeni bir pencere (iletişim kutusu) belirir belirmez, yeni pencerede basılacak tüm tuşlar WM_COMMAND'a çevrilir ve nereye gönderilir? Ve doğru söyleyeyim: Baş ağrımız kötü.

Bu aşamada en kör durumda polisi engellememenizi, bunun yerine derslerde zaten daha önce olan (veya netleşmemiş olabilecek) konuşmalara bakmanızı tavsiye ederim.

IsDialogMessage

Bu işlevin ismine dayanarak bunun şu anlama geldiğini düşünebilirsiniz: herhangi bir diyalogdan haberdar olmak. Ale, öncelikle ne biliyorsun? Başka bir deyişle bu bilginin değeri nedir?

Gerçekten biraz daha fazla ödemeye değer, adından da belli oluyor. Ve kendine:

  • Sekme/Shift+Sekme/Yukarı/Aşağı/Sağ/Sol düğmelerini kullanarak alt denetimler arasında gezinebilirsiniz. Artı bir şey daha, bu bize yeter
  • ESC tuşuna bastıktan sonra WM_COMMAND(IDCANCEL) formunu oluşturur
  • Enter'a bastıktan sonra WM_COMMAND(IDOK) oluşur veya satırdaki butona bastıktan sonra
  • Bağlantıların arkasındaki düğmelerin yerini değiştirir (bu tür düğmelerin çerçevesi diğerlerinden biraz daha parlaktır)
  • Muhabirin robotunun diyalogla işini kolaylaştıran daha da farklı şeyler
Bize ne veriyor? Öncelikle pencerenin ortasında gezinmeyi düşünmemize gerek yok. Her şeyi çok fazla saklamamız gerekiyor. Konuşmadan önce, WS_EX_CONTROLPARENT stilini ana penceremize ekleyerek Sekme gezinmesi sağlanabilir, ancak çok kullanışlı ve işlevsel değildir..

Başka bir şekilde, listede listelenen noktaların (ve daha fazlasının) parmaklıklar ardında hayatı kolaylaştırabiliriz.

Vzagali, robot güvenliği için burada Windows'un zirvesinde vikoristlik yapıyorsun kalıcı iletişim pencereleri ve programcılara kalıcı olmayan diyaloglar için üzerlerine tıklama yeteneği verilmiştir. Ancak bunu iyi bir önlem olarak kullanabiliriz:

Ayrıca, fonksiyonun iletişim işlevi iletişim kutularını modellemek için kullanılır; bunu herhangi bir pencereyle kullanabilirsiniz, böylece işaretler pencerelerde ayarlanır, klavyenin kendisinin seçildiğinden emin olmak için iletişim kutusunda kullanılabilir.
Tobto. Şimdi döngüyü şu şekilde biçimlendirelim:

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) ; GönderimMesajı(&msg);
Sonra nihayet diğer Windows diyaloglarında olduğu gibi navigasyonu kullanacağız. Ama şimdi iki eksiklik bizi elimizden aldı:

  1. Bu kod ayrıca yalnızca nazikçe kullanılacaktır bir (modal olmayan) pencereli;
  2. İletişim kutusunda gezinmenin tüm avantajlarını ortadan kaldırdıktan sonra, görünüme WM_KEYDOWN/WM_KEYUP eklememiz gerekiyor (yalnızca pencerenin kendisi için, alt denetimler için değil);
Ve bu aşamada tüm eğitimler sona eriyor ve yemek başlıyor: Winapi standart iletişim kutusunda klavye olayları nasıl ele alınır?
Bu, Google'da veya İnternette yayınlanan ilk şey: binlercesi. Önerilen çözüm hakkında (en önemlisi, alt sınıflandırma ve RegisterHotKey'den önce yukarıda yazdığım gibi kendi diyalog sınıfınızı oluşturmanız gerekir. Burada yöntemlerin "en kısasını" öğreneceğim: Windows Hooks vikorize).

Derslerde ve videolarda eksik olan şeyleri konuşmanın zamanı geldi.

Kural olarak (kural olarak! Daha fazlasını isteyen varsa diyaloglar için sınıfınızı kaydedebilir ve bu şekilde çalışabilirsiniz. Ve umursamıyorsanız bu makaleyi ekleyebilirim) WM_KEYDOWN eğer baskıyı işlemek istiyorsanız tuşuna basın ofiste gerekli kontrole bakılmaksızın işlevi seçmek için - yani. Bu özel diyalog için hayati bir işlevdir. Ve eğer durum böyleyse, o zaman neden WinAPI'nin bize öğrettiği zengin olanakları hızla tanıtmıyorsunuz: ÇeviriHızlandırıcı.

Viktorist aracılığıyla tam olarak bir hızlandırıcılar tablosu ve hatta ana pencere. Dürüst olmak gerekirse, yalnızca bir GetMessage döngüsü döngüsü vardır ve yalnızca bir tablo vardır. Nereye gitmeliler?

Aslında GetMessage döngüleri şunlar olabilir: katkılar. PostQuitMessage açıklamasına bir kez daha hayret edelim:

İşlevler PostQuitMessage, iş parçacığının mesaj kuyruğuna bir WM_QUIT mesajı gönderir ve hemen geri döner;
Mesaj Aldım:
Eğer fonksiyon WM_QUIT mesajını güncelleyecekse dönüş değeri sıfırdır.
Böylece pencere prosedüründe PostQuitMessage'ı çağırdığımızda GetMessage döngüsünden çıkış gerçekleşir. Bu ne anlama gelir?

için yapabiliriz kutanöz modal olmayan Bu, programımızın kendi güç benzeri döngüsünü yaratmasının penceresidir. DialogBoxParam bizim için uygunsa, çünkü Kendi nem döngümüzü döndürmemiz imkansızdır. Ancak CreateDialogBoxParam aracılığıyla bir iletişim kutusu veya CreateWindow aracılığıyla bir pencere oluşturursanız başka bir döngü çalıştırabilirsiniz. Ne zaman kutanöz Bu tür bir diyalog için PostQuitMessage'a tıklamamız gerekiyor:

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) ; DispatchMessage(&msg); ) ))) // .... hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), hwnd, MyDialogBoxProc), HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR_FOR_MY_DIALOG)); wnd, FALSE);// iletişim penceresi kalıcı olduğundan ana pencereyi devre dışı bırakın while (bRet = GetMessage(&msg, nullptr, 0, 0)) ( if (-1 == bRet) break; if (!TranslateAccelerator(hDlg, hAccel) , &msg)) ( if (!IsDia , &msg)) ( TranslateMessage(&msg); DispatchMessage(&msg); ) )) EnableWindow(hwnd, fSavedEnabledState); // Ana pencereyi etkinleştirin. wparam, LPARAM lparam) (switch(umsg) (case WM_CLOSE: (// EndDialog(hwnd, 0)); - BUNU YAPMAYIN! // EndDialog yalnızca DialogBox(Param) DestroyWindow(hwnd) ile oluşturulan diyalogları değiştirmek için doğrudur; break; ) case WM_DESTROY: ( PostQuitMessage(0); break; ) // .... ) return 0; )
Saygınızı yeniden kazanın: Artık programımızdaki yeni görünüm penceresini işlemeden önce ekleyebiliriz Vlasnu hızlandırıcı tablosu. WM_QUIT, GetMessage'ı iletişim döngüsünden kaldırır ve dış döngü çalışmaz. Neden bu kadar heyecanlısın?

Sağda prosedürümüze tıklanan DispatchMessage tıklandığında mevcut döngünün “ayağa kalkması”, gücünün nasıl açılacağı dahili Bu DispatchMessage'ın kendisiyle birlikte GetMessage döngüsü. Klasik wiklik ekleri (DispatchMessage'da). Dolayısıyla dış döngü WM_QUIT'i iptal etmez ve bu aşamada sona erer. Her şey sorunsuz gidiyor.

Tabi burada bazı eksiklikler var:
Cilt bu döngünün farkındadır sadece “sizin” pencereniz için. Buradaki diğerlerini bilmiyoruz. Bu, burada başka bir döngü belirirse hepsinin mesajlarını TranslateAccelerator/IsDialogMessage çiftini kullanarak işlemesi gerekeceği anlamına gelir.

Artık tüm saygılarınızı geri almanın ve programımızın tüm sonuçları hakkında sizi bilgilendirmek için her şeyin doğru şekilde işlenmesine yazıp karar vermenin zamanı geldi. Bir yayının ödülünün daha düşük olmasına saygı duymak istiyorum. Çünkü Eğer deri akışı, yapısının farkına varmasına izin veriyorsa, o zaman deri akışının da kendi yapılarını yaratması gerekecektir. Koddaki önemsiz değişikliklerden bile korkmak.

Robimo çok güzel

Çünkü Eğer bir görevi doğru ayarlamak çözümün yarısıysa o zaman önce görevi doğru ayarlamam gerekiyor.

Her şeyden önce, sadece mantıklı olurdu daha aktifŞu anda bildirimler alıyorum. Tobto. Etkin olmayan bir pencere için hızlandırıcıyı çevirmeyiz ve IsDialogMessage'a bildirim göndermeyiz.

Başka bir deyişle, hızlandırıcı tablosu pencere için ayarlanmamışsa çevrilecek hiçbir şey yoktur, yalnızca IsDialogMessage'da bir bildirim vardır.

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 şu şekildedir:

Std::harita l_mAccelTable;
Ve oluşturulan pencereler dünyasında, favori tablonuza (veya böyle bir işlem gerekli olmadığından sıfır) tanımlayıcı içeren yeni bir pencere eklemeye devam edeceğiz.

BOOL AddAccelerators(HWND hWnd, HACCEL hAccel) ( if (IsWindow(hWnd)) ( l_mAccelTable[ hWnd ] = hAccel; return TRUE; ) return FALSE; ) BOOL AddAccelerators(HWNDhW LoadAccelerators( hInstance, accel));) BOOL AddAccelerators(HWND) hWnd, int hızlanma)
Ve pencereyi kapattıktan sonra uzaklaşın. Eksen şu şekildedir:

Void DelAccel(HWND hWnd) ( std::map ::yineleyici me = l_mAccelTable.find(hWnd); if (me != l_mAccelTable.end()) ( if (me->second) ( DestroyAcceleratorTable(me->second); ) l_mAccelTable.erase(me); ) )
Şimdi yeni bir iletişim kutusu/pencere oluşturduğumuzda AddAccelerators(hNewDialog, IDR_MY_ACCEL_TABLE) öğesine tıklayın. Nasıl kapatılır: DelAccel(hNewDialog).

Gerekli tanımlayıcıların bir listesine sahibiz. Ana işleme döngümüzü şu şekilde değiştiriyoruz:

// ... 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 iyi! HandleAccelArray'de neler var ve GetActiveWindow()'da sırada ne var?

Biraz teori:

Etkin pencere tanıtıcısını GetForegroundWindow ve GetActiveWindow döndüren iki işlev vardır. Birincisinin diğerine göre önemi diğerinin açıklamasında tam olarak açıklanmış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 halde, dönüş değeri NULL'dur.
İlk önce sistemdeki herhangi bir pencerenin tanımlayıcısını döndürürseniz, geri kalanı yalnızca Vikorist'in sözü akışımızı nasıl bilgilendirecek?. Çünkü Biz sadece kendi akışımızda (ve günümüze kadar helak olacak olanlarımızda) yaşamaya devam edeceğiz, sonra kalacağız.

Yani aktif penceredeki tanımlayıcı tarafından iletilen HandleAccelArray ekseni haritamızda en görünür olanıdır ve orada olduğu gibi TranslateAccelerator yayınına bir mesaj gönderir ve ardından (sanki ilki gerekli değilmiş gibi) ) IsDialogMessage'da. Mesaj henüz gönderilmediyse, standart TranslateMessage/DispatchMessage prosedürünü uygulamak için FALSE'ı çevirin.

Şuna benziyor:

BOOL HandleAccelWindow(std::map) ::const_iterator mh, MSG & msg) ( const HWND & hWnd = mh->first; const HACCEL & hAccel = mh->second; if (!TranslateAccelerator(hWnd, hAccel, &msg)) ( // mesaj Çeviri Denemesi için değil IsDialogMessage ile if (!IsDialogMessage(hWnd, &msg)) ( // yani, varsayılan öğeler FALSE döndürür; ) ) // tamam, mesaj çevrildi (HWND hActive, MSG & msg) ( if (!hActive) FALSE döndürür; / / aktif pencere yok std::map yapacak bir şey yok. ::const_iterator mh = l_mAccelTable.find(hActive); if (mh != l_mAccelTable.end()) ( // Anladım! Aktif pencere için bu mesajı tercüme etmeye çalışın return HandleAccelWindow(mh, msg); ) return FALSE; )
Artık her çocuğun favori hızlandırıcı tablosunu ekleme ve gerekli kodla WM_COMMAND'ı sakince yakalayıp girme hakkı var.

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

TranslateAccelerator'daki açıklama şunları söylüyor:
Mesajlarla gönderme fonksiyonunun menü veya kontroller anlamına geldiğini açıklığa kavuşturmak için, wParam parametresi WM_COMMAND veya WM_SYSCOMMAND mesajına sahip yüksek etkili kelime 1 değerini içerir.
WM_COMMAND işlem kodu şuna benzer:

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 bunu şu şekilde yazabilirsiniz:

Switch(HIWORD(wParam)) ( case 1: // hızlandırıcı durumu 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önüp şunu ekledik: sadece bir satır Düğmelere yönelik komutları işleme kodunda aşağıdakileri kaldırıyoruz: klavyeden hata ayıklayıcıyı kullanın. Baş döngüsünün yakınına küçük bir kabuk ve belirli VK_KEY => IDC_DEBUGGER_BUTTON türlerine sahip yeni bir hızlandırıcı tablosu eklemek yeterlidir.

Not: Çok az kişi kendi hızlandırıcı tablonuzu oluşturmanın mümkün olup olmadığını biliyor ve şimdi onu doğrudan donduruyor.

P.P.S.: Çünkü DialogBox/DialogBoxParam güç döngüsünü döndürür, ardından diyalog onlar aracılığıyla çağrıldığında hızlandırıcılar çalışmaz ve döngümüz (veya döngülerimiz) “boşta” kalır.

P.P.P.S.: HandleAccelWindow kartlarına tıkladıktan sonra l_mAccelTable değiştirilebilir çünkü TranslateAccelerator veya IsDialogMessage DispatchMessage'a tıkladığınızda, işlemcilerimizde AddAccelerators veya DelAccel'e katılabilirsiniz! Bu nedenle bu işlevleri göz ardı etmemek en iyisidir.

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

Etiketler: Etiket ekleyin

C WinAPI, işletim sistemlerinde bulunan Microsoft program arayüzlerinin (API'ler) ana kümesidir. Eski bir sürüme Win32 API adı verildi.

Girmek

WinAPI, Windows programları oluşturmak için kullanılan bir uygulama programlama arayüzüdür. Başlangıç ​​olarak geliştiricinin daha önce Platform SDK olarak bilinen Windows SDK'yı kullanması gerekir.

Program geliştirmek için kullanılan başlık dosyalarını, kitaplıkları, görüntüleri, belgeleri ve araçları birleştirin. C ve C++ dilinde dil programlamaya yönelik API. Bu, bir şirketin işletim sisteminde eklentiler oluşturmanın en doğrudan yoludur.

WinAPI ile bunu birkaç alana bölebilirsiniz:

    temel hizmetler;

    emniyet;

  • Koristuvalnytsky arayüzü;

    multimedya;

    Windows kabuğu;

    Merezhevy hizmetleri.

Temel hizmetler temel kaynaklara erişimi sağlayacaktır. Bunlar WinAPI işlevlerini, dosya sistemlerini, aygıtları, işlemleri, iş parçacıklarını, kayıt defterini ve hata işlemeyi içerir. Güvenlik alanı, kimlik doğrulama, yetkilendirme, şifreleme ve güvenlikle ilgili diğer görevlere yönelik arayüzleri, nesneleri ve diğer programlama öğelerini içerir. Grafik alt sistemi, grafiklerin monitörlerde, yazıcılarda ve diğer görüntüleme aygıtlarında görüntülenmesine yönelik işlevsellik sağlar. Ressamın arayüzü, ressamın pencerelerinin ve elemanlarının oluşturulması için işlevsellik sağlayacaktır.

Multimedya bileşeni video, ses ve giriş aygıtlarıyla çalışmaya yönelik araçlar sağlar. Kabuk arayüzü işlevleri, programların işletim sistemi kabuğu tarafından sağlanan işlevlere erişmesine olanak tanır. Merezhevi hizmetleri Windows'ta mümkün olan maksimum ölçüde erişim sağlar.

Bileşenler

WinAPI çalışırken, Windows API'nin yedi kategoriye ayrılabilen temel özelliklerine erişebileceksiniz. Raporlarının dış görünümüne bir göz atalım.

Ana hizmetler, Windows'taki temel sistem kaynaklarına erişim sağlar. Uygulamalar: dosya sistemi, çevre birimleri, işlemler, sistem kayıt defterine ve çekirdek sistemine erişim. Bu işlevler, 16 bit sistemler için kernel.exe, krnl286.exe veya krnl386.exe ve 32 bit sistemler için kernel32.dll ve advapi32.dll dosyalarında depolanır.

Grafik arayüz, monitörlerde, yazıcılarda ve diğer çevresel ekipmanlarda görüntülenecek kaynaklara erişim sağlayacaktır. 16 bit sistemlerde gdi.exe, 32 bit sistemlerde gdi32.dll dosyasında depolanır.

Kullanıcı arayüzünün arayüzü, düğmeler ve kaydırma gibi temel öğelerin görünümü, klavye ve fareler hakkındaki bilgilerin yanı sıra bunlarla ilişkili işlevlerle karakterize edilir. Bu işlevler, 16 bit sistemlerde user.exe dosyasında ve 32 bit sistemlerde user32.dll comctl32.dll dosyasında depolanır. XP sürümünden itibaren kontroller comctl32.dll dosyasında gruplandırılmıştır.

Gizli diyaloglar - Dosyaları açmak ve kaydetmek, renkleri ve yazı tiplerini seçmek için verileri görüntüleme. Dosya 16 bit sistemlerde comdlg.dll, 32 bit sistemlerde comdlg32.dll'dir.

Windows Kabuğu, programların işletim sistemi kabuğu tarafından sağlanan işlevlere erişmesine olanak tanıyan bir WinAPI bileşenidir.

Ağ hizmetleri, işletim sisteminin maksimum yeteneklerine erişim sağlar. Alt bileşenleri NetBIOS, Winsock ve RPC'yi içerir. Eski sürümlerde NetDDE bulunur.

Sürümler

Win16, Win32 ve Win32'ler, uygulama yazılımının Windows ailesindeki çeşitli işletim sistemlerinin işlevlerini yerine getirmesine olanak tanıyan standart bileşen setleridir.

Win16'nın halefi olan Win32, 1993 yılında Windows NT, 2000, 95 gibi Windows ailesinin 32-bit ürünlerinde tanıtıldı. Bu yazılım arayüzü üç yazılım kütüphanesini uygular: Kernel32.dll, User32.dll ve GDI32.dll2. Aynı Win32 özellikleri tüm Windows ürünlerinde mevcuttur ve ürüne bağlı olarak bu özelliklerin eklenmesi hizmet sorunlarına neden olabilir.

Win32'nin yetenekleri arasında programlar arasındaki iletişim, süreç kontrolü, bilgisayar dosyaları, yazıcılar, sunucular ve iletişim bağlantı noktaları bulunur.

Şartname

WinAPI, Windows işletim sistemi için bir programlama arayüzüne yönelik soyut bir spesifikasyondur. İşlevlerin, bağlantıların, yapıların, veri türlerinin, makroların, sabitlerin ve diğer programlama öğelerinin bildirimlerinden oluşur. WinAPI başlık tarafından tanımlanır ve Windows C başlıklarında bulunur. WinAPI işlevinin resmi uygulaması dinamik kitaplıklarda (DLL'ler) bulunur: örneğin sistemdeki kernel32.dll, user32.dll, gdi32.dll ve Shell32.dll. dizin. Windows API'nin üçüncü taraf uygulamaları vardır: en önemlisi Wine projesi ve ReactOS projesi.

Windows API dinamik bir nesnedir. İşletim sisteminin her yeni sürümü ve yeni güncelleme paketleriyle birlikte işlevlerin sayısı giderek artıyor. İşletim sisteminin sunucu sürümleri ile masaüstü sürümleri arasında da önemli farklılıklar vardır. Bu işlevler resmi olarak belgelenmemiştir.

Pelles C

Pelles C, yazılım içermeyen bir programdır ve C dili programlama için en güçlü C derleyicisi ve entegre geliştirme motorudur (IDE). 32 bit Windows (x86) ve 64 bit Windows'u (x64) destekler. C99 ve C11 standartlarını uygular. Pelles Bir kaynak düzenleyici, bir bitmap görüntüsü, bir simge, bir imleç düzenleyici ve on altı döküm düzenleyici içerebilir. İsveçli perakendeci Pelle Orinius tarafından ortaya çıkarıldı. Derleyicinin adı yazarının adını taşır. SDK'ya dahil olan programcı, oluşturulan programı daha fazla kuruluma gerek kalmadan hemen yazdırabilir.

Amaca yönelik mimari

Windows API programları oluşturmak için Microsoft uzantılarını etkinleştirmeniz gerekir. Arkasında, derleyicinin sanki bozuk yapıya sahip bir C WinAPI uygulamasıymış gibi hatayla ilgili bir mesaj görmesi ile bağlantılı olarak kötü bir koku var: ölümcül hata #1014: #hata: "Hedef mimari yok." Microsoft uzantısını etkinleştirmek için proje parametrelerine gidin ve “Derleyici” sekmesini seçin. Bu sekmede “Microsoft uzantılarını devre dışı bırak” seçeneği aktiftir.

MSDN

Bu, Windows'u yüklemek için merkezi portaldır. Bu, çeşitli Microsoft araçlarından programların geliştirilmesiyle ilgili harika bir materyal koleksiyonudur. Masaüstü uygulamalarının geliştirilmesine ilişkin kapsamlı bir belge veritabanı ve Windows API'lerinin bir listesi.

WinAPI C'de Zastosuvannya DLL

Gelişmiş öğelerden oluşan kütüphane, işletim sisteminin satırlar, pencere göstergeleri, araç çubukları ve sekmeler gibi gelişmiş işlevlerine erişim sağlayacaktır. Bu komutlar, 16 bit sistemlerde commctrl.dll ve comctl32.dll kütüphanesinde bulunur ve istemci arayüzü ile gruplandırılmıştır.

DLL, Windows programları için çeşitli kodları ve prosedürleri kaydetmek için kullanılan dinamik bir kitaplık dosyası biçimidir. DLL dosyaları, bir dizi programın bilgilerine anında erişebileceği ve böylece bellek tasarrufu sağlayacak şekilde oluşturuldu. Kullanıcıların birden fazla programdaki kodu değiştirmeden düzenlemesine olanak tanır. DLL Kitaplıkları, Lib 3.00 için statik, vikorist MSIL Disassembler'a veya DLL'ye dönüştürülebilir.

Windows için bir uygulama programlama arayüzü olan WinAPI, basit dosya işlemeden düşük seviyeli aygıt sürücülerini programlamak için grafiksel bir arayüze kadar kendi programlarınızı oluşturmanıza olanak tanıyan basit işlevler sunar.

WinAPI ile programlamaya başlamadan önce Windows'ta kod için bir orta yol belirlemeniz gerekiyor. Bir Linux dağıtımı olmasa da eklenti oluşturmak için yerleşik bir derleyiciye sahip değildir. Kod derlemek için aşağıdaki seçeneklere bakalım:


Windows için, geliştiricilerin Wikimedia API ve ilgili teknolojilerle yazılım oluşturmasına olanak tanıyan belgeler ve araçlar sağlayan bir geliştirici kiti mevcuttur.

Windows API - bir dizi işletim sistemi işlevi

API kısaltması birçok acemi programcı için belirsiz ve kafa karıştırıcı görünmektedir. Aslında Uygulama Programlama Arayüzü (API), eklenti satıcıları tarafından kullanılabilecek hazır bir işlevler kümesidir. Resmi anlamda bu kavram, daha önce sıklıkla alt program kitaplığı olarak adlandırılan şeye eşdeğerdir. Ancak API'nin altında bu tür kitaplıkların özel bir kategorisinin bulunduğunu lütfen unutmayın.

Geliştirme süreci sırasında, son kullanıcı için belirli bir programın uygulanması için gerekli olan ve MyApplication API adı verilen bir dizi spesifik dahili fonksiyon oluşturulur. Ancak, bu işlevlerin diğer programlar da dahil olmak üzere başka programlar oluşturmak için etkili bir şekilde kullanılabileceği sıklıkla keşfedilir. Yazarlar, ürünlerini satma stratejisine dayanarak beslenmeyi nasıl seçiyorlar: dış müşterilerin hangi sete erişmesine neden izin veriyorlar? Onaylanırsa, yazılım paketinin olumlu bir özellik olarak açıklaması şu ifadeyi içerir: "Paket kapsamlı bir dizi API işlevi içerir" (veya ek para için).

Bu nedenle, çoğunlukla API altında, bir programın parçası olan ancak diğer programlarda kullanılabilen bir dizi işlev bulunur. Örneğin Excel, son kullanıcı arayüzüne ek olarak, örneğin VB kullanılarak oluşturulan programlarla erişilebilen bir dizi Excel API işlevine sahiptir.

Görünüşe göre, Windows API, işletim sisteminin bir parçası olan ve aynı zamanda VB kullanılarak yazılan program da dahil olmak üzere başka herhangi bir program tarafından erişilebilen bir dizi işlevdir. Bu plan, aslında DOS API'si olan sistem BIOS/DOS geçersiz kılma kümesine tamamen benzerdir.

Windows API işlevselliğinin avantajı bir yandan DOS'unkinden çok daha geniştir, diğer yandan eski işletim sistemindeki programların kullanabileceği bilgisayar kaynaklarının doğrudan kontrolüne yönelik pek çok özellik içermez. Ek olarak, Windows API'ye bağlantı ek prosedür parametrelerine dayanır ve DOS işlevine Interrupt adı verilen özel bir işlemci makine komutu aracılığıyla erişilir.

VB Programcıları İçin En Çok İhtiyaç Duyulan Win API

VB'nin çeşitli işlevleri olmasa da, az çok ciddi gelişme sürecinde, yeteneklerinin çoğu zaman gerekli görevleri tamamlamak için yeterli olmadığı ortaya çıkıyor. Bu durumda, yeni başlayan programcılar genellikle VB'nin eksikliklerini gözden kaçırmaya başlarlar ve bilgisayarlarının büyük bir maliyet kümesine sahip olduğundan ve bunlara hızlı bir şekilde girilmesi gerektiğinden şüphelenmeden aracı değiştirmeyi düşünürler.

Win API'yi öğrendiğinizde, belirli sistem prosedürlerine genişletilmiş olmaktan başka bir şey olmayan, ancak yalnızca verilen dille aynı sözdiziminde uygulanan çok sayıda kullanılmış VB işlevinin olduğu ortaya çıkar. Hızlı bir API ihtiyacına bağlı olarak mevcut seçenekler şunlardır:

  1. Genellikle VB işlevleri biçiminde uygulanan API işlevleri. Ancak zaman daha az değildir; bu durumda API durgunluğuna geçmek gerekebilir, böylece üretkenliği hızlı bir şekilde artırmanıza olanak tanır (aktarılan parametrelerde gereksiz değişikliklerin olmaması hariç).
  2. Oluşturulan VB işlevleri yalnızca API işlevlerinin bir parçası olarak uygulanır. İşte daha basit bir seçenek. Örneğin CreateDirectory API işlevi, VB MkDir operatörüne kıyasla daha büyük yeteneklere sahiptir.
  3. VB dilinin mevcut sürümünde analogları olmayan çok sayıda API işlevi vardır. Örneğin, VB kullanarak bir dizini silmek mümkün değildir - bunun için SilDirectory işlevini kullanmanız gerekir.

Ayrıca, örneğin bellek adresleriyle çalışma yeteneğinin olmaması nedeniyle, belirli API işlevlerine (bazıları Win API'sinde bile önemsizdir) bir dizi dil arabirimi aracılığıyla VB programlarından erişilemediği unutulmamalıdır. Ancak bazı durumlarda önemsiz olmayan programlama teknikleri yardımcı olabilir (aynı adreslerin olması durumunda).

Yazarın özel fikri, sürümü VB tarafından kullanılan işlevlerin sürümüne genişletmek yerine, aşağıdakilerin en yaygın API işlevlerinin iyi bir tanımını vermesidir. Aynı zamanda, geliştiricilerin genişletilmiş işlevlere sahip bir özellik için yeni bir sürümün ortaya çıkmasını beklememelerini, bunun yerine orijinal Win API stokunu dikkate almalarını rica ediyorum - yeteneklerinizin tamamen açık olduğu açıktır. ihtiyaç halihazırda VB 1.0 sürüm 1991 sürümünde uygulanabiliyordu.

Yak vivcchati Win API'si

Win32 API'nin işlev sayısının 10 bin civarında tahmin edildiğini (Microsoft gibi kimse kesin rakamı bilmiyor) hatırlamak o kadar da kolay değil.

VB deposu (sürüm 4-6), Win API - WIN32API.TXT açıklamasını içeren bir dosya içerir (uygulamasına ilişkin bir rapor daha sonra duyurulacaktır). Persher'de Ale, İnsan öncesi dönemin sona ermesiyle birlikte, vicoristovani anımsatıcıları için aynı parametrelere sahip venlerin tanınmasıyla vazgeçilebilir ve diğer yandan, tsomo dosyasının işlevlerinin perepass'ı uzaktır. gitmiş. Günümüzde (şans eseri) VB 3.0, Win16 API işlevlerini açıklayan özel kavram kanıt dosyalarına sahipti. V.4.0'da bu değerli bilgilere manuel arayüz aracılığıyla zaten ulaşılabilmektedir.

Win32 API'sine ilişkin ek bilgiler, VB 5.0, 6.0 Enterprise Edition ve Office 2000 Developer Edition ile birlikte gelen MSDN Kitaplığı CD'lerinde de bulunan önceki Platform Yazılım Geliştirme Kiti'nde bulunabilir. Ancak orada ihtiyacınız olan bilgiyi bulmak ve ona ulaşmak hiç de kolay değil. Buradaki tüm açıklamaların tamamen C.

VB ortamlarında API programlamaya dünyanın en tanıdık girişi, ünlü Amerikalı uzman Daniel Appleman'ın kitabıdır. Dan Appleman'ın Windows API Visual Basic Programcı Kılavuzu'nun bu serisi (Win16, Win32, VB'nin yüzlerce farklı sürümü için) 1993'ten bu yana sürekli olarak VB programcıları için en çok satan kitap haline geldi. 1997 yılında yayınlanan Dan Appleman'ın VB 5.0 Programmer's Guide to the Win32 API kitabı, yazara küçük bir taşra kasabasının ilk kitapçısını bilen bir arkadaşı tarafından ABD'den getirildi.

1.500'den fazla sayfadan oluşan bu kitap, VB'de API programlamaya yönelik ileri tekniklerin açıklamasını ve 900'den fazla işlevi içerir. CD, kitabın tam metnini ve tüm yazılım uygulamalarını ve ayrıca ikinci versiyonda yer almayan bazı ek bölümleri içerecektir. 1999'da Dan Appleman, diğer 7.600 işlevin (rapor panoları olmasa da) genel bakışlarını içeren Dan Appleman'ın Win32 API Puzzle Book and Tutorial for Visual Basic Programmers adlı yeni bir kitabını yayınladı.

Win API ve Dinamik Bağlantı Kitaplığı (DLL)

Dinamik DLL kitaplıkları olarak bir dizi Win API uygulaması. Daha sonra aslında Win API deposunda bulunan kitaplıkların uygulamasında VB'nin ortasına DLL yükleme teknolojisinden bahsedeceğiz. Ancak DLL'lerden bahsederken çok fazla saygı kazanmak gerekiyor.

Bu durumda, DLL altında, gerekli prosedürlere - alt programlara veya işlevlere (bir VB projesinin ortasında prosedürleri çağırırken beklenenle yaklaşık olarak aynı) doğrudan dönüşümü sağlayan iki katlı dinamik kitaplıkların geleneksel sürümüne saygı gösterebiliriz. ). Bu tür kitaplıklar diğer araçlar kullanılarak oluşturulabilir: VC++, Delphi, Fortran ve VB (sürüm 7.0'da görünür) - geri kalanı yalnızca Internet OLE Otomasyon yüzü aracılığıyla erişilebilen ActiveX DLL'leri kullanılarak çalışabilir.

Dinamik kitaplık dosyaları extension.DLL dosyasını içerebilir, ancak durum böyle olmayabilir (Win16 için extension.EXE genellikle takılıp kalır); Harici aygıtların sürücüleri ek DRV altında listelenmiştir.

Daha önce de belirttiğimiz gibi, sistem kataloğunda saklanabilmeleri için Windows API işlevlerinin ve dosyalarının tam sayısını belirlemek önemlidir. Bu plan, işletim sisteminin çekirdeğine kadar uzanan bir kütüphane deposunu ve temel ek işlevlere sahip ana kütüphaneleri daha iyi görecektir.

Ve şimdi mutluyum.

Lütfen 1. DL duyurusunun doğru formatını takip edin L-prosedürleri

Programın DLL prosedürlerine kadar olan hiyerarşisi, "birincil" Visual Basic prosedürlerine kadar olan hiyerarşiyle aynı görünür; örneğin:

DllName'i çağırın ([bağımsız değişken listesi])

Ancak, harici DLL işlevlerini (Win API dahil) kullanmak için, program tarafından aşağıdaki gibi görünen Declare deyimi kullanılarak çağrılmaları gerekir:

Alt Prosedür Adını Bildirin Lib _ “Kütüphane Adı” _ [([Argüman Listesi])]

Fonksiyonu Bildirin Fonksiyon Adı _ Lib “Kütüphane Adı” _ [([Argüman Listesi])]

Burada kare kollarda operatörün gerekli elemanları belirtilmiş, alternatif kelimeler italik, anahtar kelimeler ise italik olarak gösterilmiştir. Gelişmiş sistem, operatör sözdiziminin iyi bir tanımını sağlayacak şekilde tasarlanmıştır, bu da bazı noktaların önemini azaltır.

Harici işlevlerin çoğu modülün Genel Bildirimler bölümünde bulunur. Eğer onu bir form modülüne yerleştirirseniz, Özel anahtar sözcüğünü belirtmeniz gerekir (bu yalnızca modülün ortasında bulunur) - bu, form modülünün tüm prosedürleri için aynıdır.

Win32 API uygulamaları kümesi işlevlerle sınırlıdır (Win16 API'nin birçok Alt programı vardı). Bu, çoğunlukla bir işlemin tamamlanma kodunu döndüren Long türündeki işlevler için özellikle doğrudur.

Declare operatörü MS Basic'te zaten DOS için göründü ve dahili prosedürleri projeye iletmek için kullanıldı. İç prosedürlerin bildirimleri Alt ve İşlev açıklamalarını otomatik olarak tanımladığından Visual Basic'in buna ihtiyacı yoktur. Basic/DOS'tan uyarlanan yeni açıklama, prosedürün bulunduğu kitaplık dosyasının adını belirtmelidir. Wip API kitaplıkları Windows sistem dizininde bulunur; gereken tek şey bir dosya adıdır. Bir DLL üzerinde çalışıyorsanız emin olmak için o dosyaya yeni bir yol yazmanız gerekecektir.

Declare operatörünün açıklaması çok yer kaplıyor ve kod penceresinin yanındaki tek satıra sığmıyor. Bu nedenle, program yazarken her türlü satır aktarım şemasına dikkat etmenizi öneririz, örneğin:

Fonksiyonu Bildirin GetTempPath _ Lib “kernel32” Takma Adı ​"GetTempPathA” _ (ByVal nBufferLength As Long, _ ByVal lpBuffer As String) As Long

Ve burada farklı satırların açıklamasının tüm ana unsurları açıklanmaktadır ve okunması güzeldir.

Lütfen 2. DLL işlevleriyle çalışırken özellikle saygılı olun

Win API'nin ve çeşitli DLL işlevlerinin kullanılması, VB'nin işlevsel yeteneklerini önemli ölçüde genişletir ve çoğu zaman program verimliliğini artırmanıza olanak tanır. Ancak bedelin ödenmesi gereken bedel, özellikle geliştirme sürecinde robotik programların güvenilirliğinin azalmasıdır.

VB ara yazılımının en önemli avantajlarından biri program geliştirme sürecinin güvenilirliğidir: yorumlayıcı çerçeve altında çalışan program kodunun Windows ve VB robotunu kırmak teorik olarak imkansızdır. Programcı, parametrelerin çağrılan işleve aktarılmasının doğruluğu konusunda çok dikkatli olmayabilir - bu tür hatalar, kodun çevrilmesi işlemi sırasında veya yürütülmesi sırasında yorumlayıcının kendisi tarafından kolayca tespit edilecektir. En kötü senaryoda, hem anlam hem de nerede ve ne olduğu açısından işleme rejiminde bir kesinti olacaktır.

Windows API'nin veya diğer DLL kitaplıklarının doğrudan işlevlerinin kullanılması, veri aktarımı ve VB ortası dışındaki koda birleştirme işlemi üzerindeki kontrolü ele alır. Bu nedenle, harici işlevlerdeki bir uzlaşma, hem VB'nin hem de işletim sisteminin arızalanmasına yol açabilir. Faydaların varlığı tamamen doğalsa, bu özellikle program geliştirme aşamasında önemlidir. Bu nedenle, temel sistemin geniş işlev yelpazesi nedeniyle programcı, bunların uygulanmasının doğruluğu konusunda sorumluluk alır.

Sorun, farklı programların prosedürler arasında parametreleri aktarmanın farklı yollarına sahip olması nedeniyle daha da karmaşık hale gelmektedir. (Daha doğrusu, çoğumuz bir dizi yöntemi destekleyebildiğimiz için farklı aktarım yöntemleri tartışmaya açıktır.) Win API, C/C++ ile uygulanır ve bu sistemde kabul edilen geçiş parametrelerinin sınıflandırılmasından bahsetmemiz gerekir. birincil VB varyantı olarak.

Bununla bağlantılı olarak, API işlevlerinin VB analoglarının ortaya çıkmasının, geri kalanların VB sözdizimine uyarlanması ve veri alışverişini kontrol etmek için benzer bir mekanizmanın uygulanmasıyla doğrulandığı belirtilmelidir. Ayrıca derlenmiş bir modül oluştururken programların son geliştirme aşamasında Yerel Kod (makine kodu) yerine P kodu derleme seçeneğini seçmenin daha iyi olacağını da takdir ediyoruz. İlk başta program, makine kodunu kullanmak yerine, tercihen işletim sistemine bakarak ve olası hataları belirlemek için manuel bir mod sağlayarak bir tercümanın kontrolü altında çalışır.

Porada 3. VB ara yazılımında güvenilir API programlama için Dan Appleman'dan on öneri

API'nin çeşitli işlevleri, prosedürlerin ölçeğini büyütmek için o kadar da basit olmayan bazı yöntemlerin (VB'ye karşı) kullanılmasıyla daha dikkatli programlama gerektirir. Gelecekte yavaş yavaş kendimizi bu gıdadan mahrum bırakacağız. Şimdi Dan Appleman'ın bu konuyla ilgili tartışmalarının bir özetini (ilk versiyonu 1993'te ortaya çıktı) bazı ek yorumlarımızla birlikte sunacağız.

1. ByVal'ı hatırlayın. Bir API ve DLL, işlevlerden önce uygulandığında ortaya çıkan en yaygın sorun, ByVal anahtar sözcüğünün yanlış sözlüğünde yatmaktadır: ya onu koymayı unuturlar ya da sonunda, buna gerek olmadığında koyarlar.

Bu örnekler ByVal operatörünün parametreleri aktarmak için girişini gösterir

Parametre türü Z ByVal ByVal olmadan
Tamsayı Yığın 16 bit kapasiteye sahiptir Yığın, 16 bitlik bir tam sayının 32 bitlik adreslerini barındırabilir
Uzun Yığın 32 bit kapasiteye sahiptir Yığın, 32 bitlik bir tam sayının 32 bitlik adreslerini barındırabilir
Sicim Dizi, C'de kullanılan formata dönüştürülür (sondaki boş bayt dikkate alındığında). Yeni satırın 32 bitlik adresleri yığına yerleştirilir Yığın, satırın VB tanımlayıcısını içerir. (Bu tür tanımlayıcılar hiçbir zaman Windows API tarafından tanınmaz ve yalnızca VB için özel olarak uygulanan DLL'lerde tanınır.)

Burada, VB de dahil olmak üzere herhangi bir programlama sistemindeki parametrelerin aktarımının iki ana adımla belirlendiğini belirtmekte fayda var: gönderme (ByRef) veya değer (ByVal). İlk seçenek değişimin adresini alır (bu seçenek VB'de değişim için kullanılır), diğeri ise değerini alır. Geçerlilik ilkesi, ek bir mesajdan sonra çağrı yapan programın iletilen parametrenin değiştirilen değerine geri dönmesinin sağlanması gerçeğinde yatmaktadır.

Başlamak için aşağıdaki programları kullanarak bir deney yapın:

Dim v As Integer v = 2 MyProc(v) MsgBox'ı çağırın “v = “ & v Sub MyProc (v As Integer) v = v + 1 End Sub

Viconnya, vikamima'nın poposunu başlatan, ZINSYAM ZMINENE, RIVNE 3'ün değerleri. Sağda, Danimarka vipad'inde, Zmіnino V'nin adresleri, fiziksel olarak sığ projeksiyonlar Viclikaє, danalara iletilir. Şimdi prosedür açıklamasını şu şekilde değiştirin:

Sub MyProc (ByVal ve Tamsayı Olarak)

Sonuç olarak, testi çalıştırdığınızda v = 2'yi kaldırırsınız; bu, değişkenin çıkış değerinin prosedüre iletildiği anlamına gelir; üzerinde çalışan işlemlerin sonucu, çağıran programa döndürülmez. Değer iletim modu ayrıca Çağrı operatörünün yardımıyla aşağıdaki gibi değiştirilebilir:

Sub MyProc (v As Integer) ... Call MyProc ((v)) '(v) - kollar, değerlerin arkasındaki iletim modunu _ gösterir.

Ancak, dahili VB prosedürlerine genişlerken, Call deyiminde ByVal anahtar sözcüğünün kullanımı bastırılır; bunun yerine yuvarlak kollar engellenir. İşte bir açıklama.

Klasik versiyonda (C, Fortran, Pascal), ByRef ve ByVal modlarının önemi, veri değişim yığınına neyin yerleştirildiğine (değişim adresleri veya değerleri) bağlıdır. Temelde, yazılım emülasyonunun ByVal sürümü tarihsel olarak kullanılmıştır - zaman değişikliğinin oluşturulduğu değerlerin iletilmesi dışında yığın her zaman adresleri içerir. İki seçeneği (Klasik ve Temel) birbirinden ayırmak için ByVal modunu tanımlamanın farklı yolları vardır. Vb'deki VB rejimindeki BYVAL, yukarıdaki işaretlerin bir kısmını unutmak zorunludur: canavarın şeklini ezici, licheus programı, viclika, Zmіninov'un vilenniasını çevirin (abo dönmüyor) . "Klasik" versiyonda, bu tür bir karışıklık, sonuçlandırma prosedürünün yapıldığı saat içinde ölümcül bir ölüme yol açabilir (örneğin, vikoristin hafıza adresi yerine sıfıra eşit, değiştirilebilir değerler varsa) ).

DLL işlevleri "klasik" prensiplere göre uygulanır ve bu nedenle her argümanla veri alışverişinin nasıl yapıldığına dair net bir açıklama gerektirir. Bunun kendisi, Declare açıklaması (daha kesin olarak iletilen argümanların listesi) aracılığıyla bir bildirim işlevi olarak hizmet edebilir. Çoğu zaman, parametrelerin bir Windows API işlevine veya DLL'ye aktarılması ByVal anahtar sözcüğü kullanılarak belirtilir. Ayrıca, Declare operatöründe veya doğrudan işlev çağrılırken belirtilebilir.

Yanlış parametre aktarımının mirasının aktarılması kolaydır. Açıkça geçersiz bir adres seçerseniz bir GPF (Genel Koruma Arızası) bildirimi görürsünüz. İşlev geçerli bir adresten kaçan değerleri aldığından, API işlevi yabancı bir alana (örneğin, Windows çekirdeğine) girerek her türlü felaketle sonuçlanan sonuçlara neden olur.

2. Aktarılan parametrelerin türünü değiştirin. Aktarılan parametrelerin doğru sayısı ve türü de aynı derecede önemlidir. Declare'de bildirilen argümanların API fonksiyonunun parametrelerine karşılık gelmesi gerekir. Parametrelerin aktarılmasıyla ilgili en büyük sorun, NULL ile bir sıfır satırı arasındaki farkla (bir ve aynı olan bellek izi) ilgilidir.

3. Döndürülmekte olan değerin türünü kontrol edin.

VB, işlev tarafından döndürülen değer türlerinin çeşitliliğini ayarlama konusunda toleranslıdır ve bazı sayısal değerler yığın aracılığıyla değil, kayıtlar aracılığıyla döndürülür. Aşağıdaki kurallar, API işlevi tarafından döndürülen doğru değerleri belirlemenize yardımcı olacaktır:

  • Değerleri döndürmeyen bir DLL işlevi ('C'deki void işlevine benzer), VB Sub gibi basitleştirilebilir.
  • Bir değeri (Tamsayı veya Uzun) döndüren bir API işlevi, Sub veya belirli bir türdeki değerleri döndüren bir İşlev olarak belirlenebilir.
  • Bu API işlevi kayan noktalı sayıları döndürmez, ancak DLL'ler bu tür verileri döndürebilir.

4. As Any yapısını büyük bir dikkatle kullanın. Birçok Windows API işlevi, farklı türdeki parametreleri kabul etme ve bunları As Any yapısına dayalı olarak kullanma yeteneğine sahiptir (türün yorumlanması, iletilen diğer parametrelerin anlamına bağlıdır).

İyi çözümler her durumda birden fazla takma ad (Alias) işlevine sahip olabilir; bunlardan iki veya daha fazlası aynı işlevleri paylaşabilir ve her açıklamanın bir parametresi ve şarkı söyleme türü vardır.

5. Satırları başlatmayı unutmayın. Win API'nin, parametre olarak iletilen satır arabelleklerinden veri toplayarak bilgileri döndüren basit bir işlevi vardır. Programınızda her şeyi doğru yapabilirsiniz: ByVal'i unutmayın, parametreleri fonksiyona doğru şekilde iletin. Ancak Windows, görülen depolama alanının boyutunun bu kadar büyük olduğuna inanamıyor. Satırın boyutu, içine yerleştirilebilecek tüm verileri barındırmaya yeterli olmalıdır. Gerekli boyutta bir arabellek ayırma sorumluluğu VB programcısına aittir.

Lütfen, 32 bit Windows'ta, farklı satırlarla, ulusal sistem ayarlarına bağlı olarak Unicode'dan (çift bayt kodlama) ANSI'ye (tek bayt kodlama) ve geriye dönüştürmenin mümkün olduğunu unutmayın. Bu nedenle arabellekleri ayırmak için normal diziler yerine bayt dizilerini kullanmak genellikle daha güvenlidir. (Bu konuyla ilgili bir rapor aşağıda ele alınacaktır.)

Çoğu Win API işlevi, maksimum blok boyutunu kendiniz ayarlamanıza olanak tanır. Örneğin bloğun boyutunu belirtmek için başka bir API fonksiyonunu çağırmanız gerekir. Örneğin GetWindowTextLength, GetWindowText işlevinin içerdiği pencerenin başlığını yerleştirmek için gereken satırın boyutunu belirlemenize olanak tanır. Bu nedenle Windows, sınırın ötesine geçmeyeceğinizi garanti eder.

6. Vikorize Seçeneği Her iki dilde de açık.

7. Parametrelerin değerlerini ve döndürülen değerleri dikkatlice kontrol edin. VB türleri doğrulama potansiyeline sahiptir. Bu, eğer bir VB fonksiyonuna yanlış bir parametre aktarmaya çalışırsanız, olabilecek en kötü şeyin VB'den gelen hata mesajını reddetmeniz olduğu anlamına gelir. Ne yazık ki, bu mekanizma Windows API işlevine yükseltildiğinde çalışmaz.

Windows 9x, çoğu API işlevinin parametrelerini kontrol etmek için gelişmiş bir sisteme sahiptir. Dolayısıyla bu verilerde af bulunması, ölümcül bir tazminat anlamına gelmese de buna neyin sebep olduğunu tespit etmek o kadar da kolay değil.

Burada bu tür sütü iyileştirmenin çeşitli yollarını bulabilirsiniz:

  • API işlevinin dış görünüm yanıtını kontrol etmek için dış görünüm modunu veya Debug.Print'i kontrol edin. Her şeyin normal sınırlar içinde olduğundan ve işlevin doğru şekilde tamamlandığından emin olmak için bu tıklamaların sonuçlarını inceleyin;
  • Vikorist, CodeView türünün Windows geliştiricisi ve Windows'un özelleştirilmiş sürümü (Windows SDK'dan). Bu işlevler parametrelerdeki değişiklikleri algılayabilir ve en önemlisi hangi API işlevinin değiştirileceğini belirleyebilir;
  • Parametre türlerini ve değerlerinin kabul edilebilirliğini doğrulamak için üçüncü taraf şirketlerin ek özelliklerini kontrol edin. Bu tür yöntemler yalnızca parametre değişikliklerini bulmakla kalmaz, aynı zamanda VB koduna değişikliğin nerede yapıldığını da söyler.

Ayrıca API fonksiyonunun sonucunu dikkatlice kontrol etmek gerekir.

8. VB ve Windows'taki sayıların aynı olmadığını unutmayın.Öncelikle VB'de “Tamsayı” teriminin 16 bitlik bir sayı anlamına geldiğini, Win 32 belgelerinde ise 32 bitlik bir sayı anlamına geldiğini hatırlayalım. Başka bir deyişle, VB'deki tamsayı sayılar (Tamsayı ve Uzun) işaretsiz değerler değildir (bir basamak işaret olarak, diğeri bir sayının mantisi olarak kullanılır), Windows'ta - bilinmeyen sayılar bile kullanılır. Ek aritmetik işlemler kullanarak bir parametre oluşturursanız (örneğin, bir taban ve ofsetin ek ikamesi kullanılarak bir adresin hesaplanması) bu durumun dikkate alınması gerekir. Hangi standart VB aritmetik fonksiyonlarının uygun olmadığı. Bu durumdan neden korkuyorsunuz, gelin bunu konuşalım.

9. İşlev adlarına dikkat edin. Win16'da, tüm Win32 API işlevlerinin adları, küçük ve büyük harflerin tam değişimine duyarlıdır (Win16'da bu yoktu). Büyük bir yazıcının yerine küçük bir yazıcı koyarsanız gerekli işlev bulunamayacaktır. Ayrıca satır parametrelerini ayarlamak için işlevlerde doğru A veya W sonekini izleyin. (Bununla ilgili rapor – aşağıdaki bölüm.)

10. Çalışmanızın sonuçlarını mümkün olduğunca sık kaydedin. Yanlış DLL ve Win API komut dosyalarıyla ilişkili hatalar, VB ara yazılımının ve muhtemelen tüm işletim sisteminin çökmesine neden olabilir. Lütfen test çalıştırmasından önce kodunuzun kaydedildiğinden emin olun. En basit şey, VB ortamında projeye başlamadan önce modüllerin projeye otomatik olarak yazılması modunu ayarlamaktır.

Bir öncekini okuduktan sonra Win API fonksiyonunun sağdan kaldırılmış olması dikkatinizi çekebilir. Bu arada, bu doğrudur, ancak yalnızca VB'nin sağladığı güvenli programlamaya uygun olarak. Ancak hafif durgunluk ve bilinen olası tehlikeler durumunda bu risk minimum düzeydedir. Ek olarak, Win API'sinin durgunluğuyla baş etmek çoğu zaman imkansızdır - ciddi bir gelişme durumunda buna yine de ihtiyaç duyulacaktır.

Bundan önce, geniş bir DLL sınıfı için "su altı" taşlarını daha önce düşünmüştük. Win API ile her şey çok daha basittir, çünkü bu işlevlerin uygulanma biçimi açıkça birleştirilmiştir. Anneye saygıda dikkat edilmesi gereken başlıca noktalar şunlardır:

  1. Win32 API'nin işlevleri, İşlev türünün işlevleri veya prosedürleridir (Win16 API'nin birçok Alt programı vardı). Tüm işlevler Long tipindedir, bu nedenle açıklamaları şu biçimde yazılır: İşlev adını Bildir ... As Long 'işlev türü _ açık biçimde belirtilir

    Bildir İşlev adı& 'işlev türü _ ek sonekle gösterilir

    API işlevine dönüşüm şu şekilde görünür:

Sonuç& = ApiAdı& ([ Argümanların Listesi]
  1. Döndürülen en önemli fonksiyon işlem tamamlama kodudur. Ayrıca, sıfır olmayan bir değer normal tamamlanma anlamına gelirken, sıfır değer yürütme anlamına gelir. Bir kez daha (veya daha önce değil), GetLastError işlevini kullanarak değişikliğin niteliğini netleştirebilirsiniz. Bu fonksiyonun açıklaması şuna benzer: Declare Function GetLastError& Lib “kernel32” ()

    UVAGA! Affın değerli kodlarının ryannatı için orta yüzlü VB'deki Robotta, vicoristovati gücünden daha fazlası güçlü Lastdlleror Op'kta Err, MIZh endüstrisindeki GetlasterRor fonksiyonunun API vicandani'sine bb іnodi vene tanklar.

    GelLastError'ı oluşturan kodu, API32.TXT dosyasında yazılan ve ERROR_ sonekiyle başlayan adlara sahip ek sabitleri kullanarak yorumlayabilirsiniz.

    En yaygın saldırı türleri aşağıdaki kodlardır:

    • ERROR_INVALID_HANDLE = 6& - yanlış tanıtıcı
    • ERROR_CALL_NOT_IMPLEMENTED = 120& - yalnızca Windows NT için kullanılabilen Windows 9x işlevlerine çağrı
    • ERROR_INVALID_PARAMETER = 87& - yanlış parametre değeri

    Bununla birlikte, belirli bir parametrenin değerlerini döndürmek için pek çok işlev vardır (örneğin, OpenFile, bir dosya açıklamasının değerlerini döndürür). Bu durumda değer, çoğunlukla 0 -1 olmak üzere diğer bazı özel Return& değerlerine atanır.

  2. Win32 API, en basit veri türlerini aktarmak için kesinlikle sabit yöntemlere sahiptir. a) ByVal...As Long

    Bağımsız değişken aktarmanın en az %80'i Long türüyle yapılır. Argümanı gözden geçirin Öncelikle ByVal anahtar sözcüğü eşlik eder ve bu, diğer şeylerin yanı sıra, VB programlarından bir API işlevine kadar tek yönlü veri aktarımının bağlantılı olduğu anlamına gelir.

    B) ByVal...As String

    Bu tür aktarım aynı zamanda sıklıkla meydana gelme eğilimindedir ve aynı argümanla Öncelikle ByVal sıkışıp kalıyor. Bir API işlevi çağrıldığında, yığına satır adresleri yazılarak iki yönlü veri alışverişine olanak sağlanır. Sıra halinde çalışırken bazı sorunlara dikkat etmek gerekir.

    İlk olarak, satırlar için bellek rezervasyonu, çağıran program tarafından gerçekleştirilir, dolayısıyla API işlevi satırları saklayacaksa, onu çağırmadan önce gerekli boyutta bir satır oluşturmak gerekir. Örneğin GetWindowsDirectory işlevi, 144 karakterden fazla yer kaplaması gerekmeyen Windows dizininin yolunu döndürür. Görünüşe göre, bu işlevin uygulanması şöyle görünebilir:

    WinPath$ = Space$(144) ' _ 144 karakterlik ayrılmış satır Result& = GetWindowsDirectory& (WinTath$, 144) _ ' arabellek doldurma ' Result& - ad _ dizinindeki gerçek karakter sayısı WinPath$ = Left$(WinPath, Result&)

    Diğer bir sorun, bir API işlevi bir API işlevine dönüştürüldüğünde, çıktı satırının dahili ekranında yeniden oluşturulması ve işlevden çıkarken de aynı şekilde gerçekleşmesi gerçeğinde yatmaktadır. Tıpkı Win16'nın ilk günlerinde bu işlemin örneğin bir satır gibi sıfır bayt eklenmesinden daha az zaman alması gibi, daha sonra Win32'nin gelişiyle çift baytlı Unicode kodlamanın ANSI'ye dönüştürülmesi ve aynı zamanda elde edildi. (Bu, Computer Press 10'99 ve 01'2000 tarihli “VB'de satır değişiklikleri olan robotların özellikleri” başlıklı makalede rapor edilmiştir). Sadece ByVal'in yardımıyla... String yapısı olarak sembolik veri satırlarının değişiminin mümkün olması önemlidir.

    B) ... Herhangi Bir Şekilde

    Bu, bellek arabelleği adresinin değerinin yığına yerleştirileceği anlamına gelir; örneğin API işlevinin ne işleyeceği yerine yorum, diğer argümanların anlamından bağımsızdır. Ancak As Any yalnızca Declare operatöründe kullanılabilir; belirli bir işlev uygulandığında bağımsız değişkene belirli bir değer atanabilir.

    D) ... UserDefinedType olarak

    Böyle bir yapı, başka bir yapı uğruna veri alışverişi (suçlu tarafın vaadi) gerektiğinde de sıklıkla takılıp kalır. Aslında bu tasarım, As Any iletim formunun basit bir spesifik uygulamasıdır, sadece her fonksiyonun sabit bir yapısı vardır.

    Veri yapısının biçimi belirli bir API işlevi tarafından belirlenir ve bunların doğru şekilde tanımlanması ve aynı programda rezerve edilmesi programın sorumluluğundadır. Bu tasarım Öncelikle vikorist olmadan ByVal kelimeleri, ardından gönderdikten sonra aktarım bu kutuya eklenir - değişim adresi yığına yazılır.

API işlevine ayak uydurun

Bu, dosyalarla çalışmanın iki temel işlevi örneği kullanılarak gösterilmektedir: lopen ve lread, bunlar aşağıda açıklanmıştır:

Fonksiyonu Bildir loopen Lib "kernel32" _ Alias ​​​​"_lopen" (_ ByVal lpFileName As String, _ ByVal wReadWrite As Long) As Long Bildir Fonksiyonu lread Lib "kernel32" _ Alias ​​​​"_lread" (_ ByVal hFile As Long, lpBuff _ ByVal wBytes As Long) As Long

VB'de bunların analogları - bazen daha kesin - Open ve Get operatörleridir (İkili mod için). Boş fonksiyonda Alias ​​​​anahtar kelimesinin kullanılmasından çok etkilendik - eğer onsuz yapamıyorsanız, bu da aynı problemdir. Kitaplıktaki bu işlev adları, VB tarafından izin verilmeyen bir sandalye altı sembolüyle başlar (C filmi için tipik stil).

Bir dosyayı açma işlemi şu şekilde görünebilir:

Const INVALID_HANDLE_VALUE = -1 ' geçersiz _ değer açıklaması lpFileName$ = “D:\calc.bas” ' dosya adı wReadWrite& = 2 ' okuma-yazma modu hFile& = lopen(lpFileName$, wReadWrite&) _ ' valued = INVALID_HANDLE _VALUE Sonra _ ' dosyayı düzeltin ' düzeltme kodunu belirtin CodeError& = Err.LastDllError 'CodeError& = GetLastError _ ' bu yapı çalışmıyor End If

Burada iki noktayı vurgulamamız gerekiyor:

  • Fonksiyonun değeri olarak dosya açıklamasının değerini belirliyoruz. Değer, -1 değerini doğrular;
  • Bu durumda GetLastError işlevine gitmeye gerek yoktur - hatanın belirtilen değerini almak için Err nesnesine gittik (böyle bir durumun olasılığı hakkında daha fazla konuştuk).

Daha sonra dosya yerine okuyabilirsiniz, ancak bu aynı zamanda programın yapısının tespitinden sorumlu olduğunu da belirtir (birden fazla çift dosyayla çalışırken olduğu gibi). Bu durumda lread fonksiyonunun açıklaması şu şekilde görünebilir:

Dim MyVar As Single wBytes = lread (hFile&, MyVar, Len(MyVar) ' konuşma sayısının okunması, 4 bayt ' wBytes - gerçekte okunan veri sayısı, '-1 - parite... Type MyStruct x As Single i As Integer Bitiş Türü Dim MyVar As MyStruct wBytes = lread (hFile&, MyVar, Len(MyVar)) ' okuma veri yapısı, 6 bayt

Bir kez daha saygı gösterin: işlevin diğer argümanı göndericilere ve değerlere geri dönüşe iletilir.

Dim MyVar As String MyVar = Space$(10) ' 10 karakter için yer ayır wBytes = lread (hFile&, ByVal MyVar, Len(MyVar)) ' okuma karakter dizisi, 10 karakter

Burada daha önce tanıtılan poponun önemini görebilirsiniz - satır değişikliğine mutlaka ByVal anahtar kelimesi eşlik eder.

Bir dizideki dosya yerine okuma (basitlik açısından tek baytlık bir dizi kullanacağız) şu şekilde derlenir:

Dim MyArray(1 To 10) As Byte wBytes = lread (hFile&, MyArray(1), _ Len(MyArray(1))* 10) ‘ diziden 10 öğe oku

Dizinin ilk elemanını argüman olarak belirterek, dizi için ayrılan hafıza alanının başının adresini iletiyoruz. Açıkçası, bu yöntemi kullanarak bir dizinin herhangi bir parçasını saklayabilirsiniz:

WBytes = lread (hFile&, MyArray(4), _ Len(MyArray(1))* 5) 4.'den 8.'ye kadar dizi öğelerini okuma

Porada 5. Transfer için Vickory Takma Adı Ayarlar Herhangi Bir Şekilde

Burada ön popoyu temel alarak Dan Appleman adına dördüncünün özünü ortaya çıkarıyoruz.

Lread işleviyle çalışırken, kendisinden önce sıradan bir değişken çalıştırırken ByVal anahtar sözcüğünün kullanılması gerektiğini hatırlamak önemlidir (aksi takdirde yasa dışı işlemle ilgili bilgiler kaybolmaz). Güvenli tarafta olmak için, yalnızca yaygın değişikliklerle çalışmak üzere bu işlevin ek özel bir açıklamasını oluşturabilirsiniz:

Fonksiyonu Bildirin lreadString Lib “kernel32” _ Alias​​“_lread” (_ ByVal hFile As Long, ByVal lpBuffer As String, _ ByVal wBytes As Long) As Long

Bu açıklamayla çalışırken artık yazdırırken ByVal'ı belirtmenize gerek yoktur:

WBytes = lreadString(hFile&, MyVarString, _ Len(MyVarString)) '

Görünüşe göre Declare operatörünün sözdizimi bir dizi için böyle özel bir açıklama oluşturmanıza izin veriyor:

Fonksiyonu Bildirin lreadString Lib “kernel32” Takma adı “_lread” (_ ByVal hFile As Long, lpBuffer() As Byte, _ ByVal wBytes As Long) As Long

Koruma hayvanı

WBytes = lreadArray(hFile&, MyArray(), 10)

kaçınılmaz olarak programın ölümcül bir şekilde yürütülmesine yol açar.

Bu, Visual Basic satır değişikliklerinin işlenmesinin özellikleri hakkındaki tartışmanın devamıdır: VB, çift baytlı Unicode kodlamayı, Win API - tek baytlı ANSI'yi (ve C'de kabul edilen, sonunda sıfır baytlı bir formatla) kullanır. Bağımsız değişken olarak satır değişikliklerini değiştirirken, bir API işlevini (daha doğrusu bir DLL işlevini) çağırdığınızda Unicode'dan ANSI'ye dönüştürmenin otomatik olarak gerçekleştirildiği ve dönüşümün döndürüldüğünde gerçekleştirildiği açıktır.

Buradaki sonuç basittir: Değişken String'lerin yardımıyla sembolik verileri paylaşabilirsiniz, ancak bunlar yeterince çifte bilgi alışverişi yapmak için kullanılamaz (VB'nin 16 bit sürümleriyle çalışırken olduğu gibi). Tek boyutlu bir bayt dizisi kullanmak daha iyidir.

Görünüşe göre String tipi yapının yapısını tanımlamak için kullanılabilir. Bu hafıza ile bağlantı aşağıdaki gibidir:

  • Win API'sini geliştirmek için saldırgan tipte bir yapı kullanmak kategorik olarak mümkün değildir: MyStruct x As Single s As String alternatif çeyiz satırı yazın

    Geçiş sırasına göre satır tanımlayıcı, programın görünümündeki tüm miraslarla birlikte iletilir.

  • Bir sıra sabit ikiye katlamanın yapı elemanı olarak mümkündür: Type MyStruct x As Single s As String*8 ‘ satır sabit ikiye katlama End Type

Bu durumda kodu yeniden oluşturduğunuzdan emin olun.

Ve saygı devam ediyor: API işlevine aynı anda yükseltildiğinde satır değişiklikleri dizisini (hem sabit hem de değiştirilebilir) birleştirmek mümkün değildir. Aksi halde “yasadışı bir işlemin” ortaya çıkması garanti altına alınacaktır.

Kütüphanenize bir DLL fonksiyonu yazmanız gerekiyorsa kötü bir durumda olduğunuz oldukça açıktır. Bir programı uygulamak için iki veya daha fazla programın birleşimi olan karma programlama teknolojisini kullanırsanız, ihtiyaç kaçınılmaz olarak ortaya çıkacaktır.

Kapsamlı bir rapor elde etmek için karma programlamanın uygulamanın temel amacı olması nedeniyle önemlidir. Aslında, dil dilinin (daha doğrusu dile dayalı programlama sisteminin) güçlü ve zayıf yönleri vardır, bu nedenle çeşitli görevleri gerçekleştirmek için çeşitli araçların avantajlarını kullanmak tamamen mantıklıdır. Örneğin, VB - bir bilgisayar arayüzü oluşturmak için, C - sistem kaynaklarına etkili erişim için, Fortran - sayısal algoritmaların uygulanması için.

Yazarın fikri şu: programlamaya ciddi katılım, geliştirici tarafından iki araç kullanılarak vurgulanıyor. Açıkçası, modern zihinlerde iki sistemde bağımsız uzman olmak çok zordur, bu da "ana ve ek dil" şemasını daha mantıklı hale getirir. Buradaki fikir, "ek" dil bilgisini (bir dizi basit prosedürle yazılmış) getirmenin "ana" dilin etkililiğini önemli ölçüde artırabileceğidir. Ek bir fayda olarak VB bilgisinin artık profesyonel bir programcı için pratik bir gereklilik olması önemlidir. Konuşmadan önce, DOS kursu sırasında herhangi bir programcı için Basic'e bakalım, Assembler'ın temellerini bilmek son derece önemli olacaktır.

Yani durum farklı, ancak grup robotlarının kafasında, cilt programcısı kendi özel çalışmasıyla meşgul olduğunda, prosedürel arayüzün özelliklerine ilişkin farklı dillerdeki ifadeler, projedeki tüm katılımcıların hatasıdır. Çok sayıda programlama sisteminin (VB dahil) olduğunu biliyorum, açıklanması gereken arayüze ek olarak, başka yöntemler oluşturmak, işleme yöntemlerini arayüzü diğer dillere uyarlamanıza izin veren prosedürlere genişletmek mümkündür. .

Prosedürler arası arayüzü kullanırken aşağıdaki olası tehlikelere dikkat edin:

  • Tanımlayıcı yazma kuralları konusunda farklı diller ilginizi çekebilir. Örneğin VB'de gizlenen prosedürün adının takma adı sıklıkla kullanılır. Bu sorun Declare operatöründe Alias ​​​​anahtar kelimesinin kullanılmasıyla kolayca açıklanabilir (2.3 için mükemmel bir örnek).
  • Yığına iletilen yazma argümanlarının sırasını belirleyebilirsiniz. Örneğin, DOS saatlerinde (dürüst olmak gerekirse, Windows'un ortasında nasıl göründüğünü bilmiyorum), listenin sonundaki argümanları, diğer dilleri (Fortran, Pascal, Basic) - başlangıç.
  • Talimatlar veya anlamlar için parametrelerin aktarılmasına ilişkin çeşitli ilkeler açıklanmaktadır.
  • Rütbeyi ve sırayı korumanın katı ilkeleri. Örneğin, C'de (Fortran ve Pascal'da olduğu gibi), bir satırın sonu, sonundaki sıfır baytla gösterilir ve Basic'te sonu, satır tanımlayıcısında açıkça yazılır. Açıkçası, sembollerin farklı kodlarını değiştirme yeteneğini hatırlamak gerekir.
  • Zengin dünya dizilerini aktarırken, zengin dünya yapılarını tek dünyaya dönüştürmek için farklı seçeneklerin olduğunu unutmayın (ilk dizinden veya geri kalanından başlayarak yüz iki boyutlu dizi - "satırlar halinde" veya "satırlar halinde" arılara").

Buna dayanarak aşağıdaki öneriler formüle edilebilir:

  • Bağımsız değişkenlerin bir DLL işlevine aktarılma biçimini gözden geçirerek en basit şeylere göz atın. Win API için benimsenen standartlar tamamen tutarlıdır.
  • Her zaman kitlesel sıradan askerleri transfer etmeyin.
  • Basit sıradan ve zengin dizilerin aktarımını saygılarımla vikorist.
  • Argümanları çağrılan ve geri gönderilen prosedüre iletme mekanizmasının işlevselliğini dikkatlice kontrol ettiğinizden emin olun. Verileri doğrulamak için özel bir test yazın. Cilt argümanının aktarımının doğruluğunu dikkatlice kontrol edin. Örneğin, çok sayıda bağımsız değişken içeren bir prosedürünüz varsa, önce tek bağımsız değişkenli seçenek için dış görünüm parametresini geçirmenin doğruluğunu, ardından da tüm liste için kontrol edin.

DLL işlevi zaten örneğin Fortran'da yazılmışsa ancak giriş arayüzü yeni VB standardına pek uymuyorsa ne olur? Burada iki tarih verebilirsiniz. İlk olarak: bir test DLL işlevi yazın ve bunun yardımıyla, VB programları için gerekli işlevselliği seçmek üzere deneme yanılma yöntemini kullanmayı deneyin. Bir diğeri: Fortran'da, bir depodaki basit veri yapılarının dönüştürülmesiyle (örneğin, bir satır dizisinden büyük bir bayt dizisinin dönüştürülmesi) VB ile bir DLL işlevi arasında basit bir arayüz sağlayacak bir bağdaştırıcı prosedürü yazın.

Otzhe: vykorist DLL işlevleri. Ayrıca tatlılığı da koruyun.

BilgisayarPress 9"2000

Bu makale, C++ programlamaya yeni başlayan ve WinAPI kullanmak zorunda kalan kişilere yöneliktir.
Oyunun önüne geçmek istiyorum:
C++ veya WinAPI gurusu gibi davranmıyorum.
Daha yeni başlıyorum ve burada WinAPI'nin fonksiyonlarını ve mekanizmalarını kullanmayı kolaylaştıracak bir takım uygulamaları tanıtmak istiyorum.

Bu yazıda, sınıflar oluşturabilmek ve onlar için farklı operatörler aktarabilmek için C++'a zaten aşina olduğunuzu ve sınıflara yönelik mekanizmalarınızı zaten "sevdiğinizi" varsayıyorum.

Konsolun oluşturulması ve vikoristanı

Win32 programlarını geliştirmek için ya da sadece ortada her şeyin nasıl göründüğüne hayret etmek için her zaman konsolu çizeceğim.
Konsol yerine bir GUI uygulaması oluşturduğunuz için konsola bağlanmayacaktır. İnternette tıklamak için bu kodu bulabilirsiniz.

Eğer (AllocConsole())
{



std::ios::sync_with_stdio();
}
Netlik sağlamak için Raja bunu bir fonksiyona sarıyor. Örneğin:
void CreateConsole()
{
if (AllocConsole())
{
int hCrt = _open_osfhandle((long)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();
}

Konsol yalnızca görüntüleme modunda çalışır ve konsol programlarıyla aynı şekilde çalışır. Bilgileri daha önce olduğu gibi girin - cout/wcout.
Bu kodun etkili olabilmesi için projeye aşağıdaki dosyaların dahil edilmesi gerekmektedir:
#katmak
#dahil et #dahil et
ve global ad alanında std ad alanını etkinleştirin:
ad alanı std'sini kullanma;
Elbette, eğer hiçbir şey yapmak istemiyorsanız, içindeki tüm varlıklara std:: eklemeniz yeterlidir.

Gösterim ve aritmeler için nesnelerin yerleşimi. operasyon

“Nihayet”i oluşturup girdikten sonra, öncelikle tüm değerleri konsola çıkarmalısınız.
Örneğin:
Bu nesneyi verilerle doldurmak için parametrenin RECT yapısının nesnesinin adresine iletildiği GetClientRect ek işlevini kullanarak pencerenin istemci alanının boyutunu belirlersiniz. Yakalanan istemci alanının boyutunu bilmeniz gerekiyorsa bunu zaten bağlı olan konsola yazmanız yeterlidir.

Cout<

Bira'nın bu kadar hızlı çalışması (özellikle de sıklıkla bu şekilde çalışmak zorunda olduğunuz için) kolay değildir.
Sakinliğin yardımımıza geldiği yer burasıdır.
RECT yapısından açıkça çöken bir sınıf oluşturun ve çıktı ifadesini yeniden amaçlayın<< так, как вам угодно.
Örneğin:

Yeni doğru sınıfı: genel RECT
{
halk:
arkadaş ostream ve operatör<<(ostream &strm,newrect &rect)
{
dizi<<"Prtint RECT object:\n";
dizi<strm'yi döndür;
}
};

Şimdi cout/wcout kullanarak nesneyi yazdırın:

Cout<

Ve her şeyin ihtiyacınız olan şekilde orada olduğunu kendiniz görebilirsiniz.
Ayrıca ihtiyacınız olan operatörlerle de çalışabilirsiniz.
Örneğin, yapıları değiştirmeniz veya atamanız gerekiyorsa (örneğin, RECT veya POINT) - operatör==() ve operatör=()'yi tamamen değiştirin.
Operatörü daha az uygulamak istiyorsanız< что бы быстро сравнивать размеры окна и т.д. перегрузите operator<().
Yani herhangi bir yapıyla bile çalışabileceğinizi ve her şeyden önce RECT yapısının birincil nesnesiyle çalışan tüm işlevlerin onunla iyi çalışacağını varsayıyorum.
Ayrıca tüm bu güzellikleri bağlantılı ayrı bir dosyaya koymanızı ve gerekirse düzenlemenizi öneririm.

Senin sınıfın

Başkalarını bilmiyorum ama ben tamamen yeşilim, cilt işlevi için veya kitabın cilt bölümü / alt bölümü için yeni bir proje oluşturmaya karar verdim, böylece her şey yolundaydı ve dönüş mümkün olacaktı. her an etrafınızda ve hafızanızda tazeleyin' Bunlar gerekli anlardır.
WinAPI'de basit bir pencere oluşturmak için sınıf yapısını doldurmanız, kaydetmeniz ve önemsiz bir pencere prosedürü yazmanız gerektiğinden, üçüncü veya dördüncü projeden sonra hala C++ ile yazdığımı fark ettim.
Sonuç olarak, basit bir sınıftan her şeyi aldım. Pencere tanıtıcısı, pencere adı, sınıf adı, pencere prosedür adresleri, pencere sınıfı (WNDCLASS) tümü özel sınıf bölümünde saklanır.
Bunları çıkarmak için basit bir "Al" yöntemini tanımlamanız gerekir, örneğin:
HWND GetHWND()
LPCTSTR GetClsName() vb.
Pencere sınıfının yenilenmesi ve tescili, pencerenin kendisinin oluşturulması ve görüntülenmesi tasarımcı tarafından gerçekleştirilir.
İşleri kolaylaştırmak için yapıcıyı yeniden planlayabilir ve pencere sınıfının tamamlanmasını ve kaydedilmesini sınıf için özel bir işleve sarabilir ve onu her bir kurucudan çağırabilirsiniz. Geri almanın avantajı, bazen tamamen basit bir pencere oluşturmanın gerekli olması ve yapıcıya iki parametreyle tıklamamdır - pencerenin adı ve programın engeli.
Aksi takdirde, varsayılan pencere prosedürü veya başka bir stil ile değil, özel boyutlarda bir pencere oluşturmaya gerek yoktur - ilişkili parametrelerle yapıcıya tıklıyorum.
Bu sınıf, IDE'nin include klasöründe bulunan, doğrudan dahil edilen dosyada daha az değere sahiptir.
Bu sınıf için bir şablon:
sınıf BaseWindow
{
WNDCLASSEX_wcex;
TCHAR_sınıfAdı;
TCHAR_windowName;
HWND_hwnd;
bool _WindowCreation();
halk:
BaseWindow(LPCTSTR windowName,HINSTANCE hInstance,DWORD stili,UINT x,UINT y,UINT yüksekliği,UINT genişliği);
BaseWindow(LPCTSTR windowName,HINSTANCE hInstance);
const HWND GetHWND()const(return HWND;)
LPCTSTR GetWndName()const(return _windowName;)
};

Böyle bir dersi iyice düşünüp yazdıktan sonra, hayatınızı kolaylaştıracak ve aynı şeyi aynı anda yazmaya başlamak için bir saatten fazla zaman harcayacaksınız. Tim'e daha çok, buna daha da güzel saygı duyuyorum - böyle bir sınıfı kendiniz yaratmanız ve ihtiyaçlarınıza göre tamamlamanız.

Not:

Açıklanan her şey aşağıdakiler için doğrudur:
Platform - Windows 7 32 bit
IDE - Visual Studio 2010
Belki birileri kahkaha ve ironi yapmak isterdi ama sonuçta hepimiz yeni gelen/stajyer/son sınıf öğrencisi olduğumuzu düşünüyorduk.
Gönderinizden önce dikkatli olmanızı rica ediyorum. Yapıcı eleştiri elbette uçup gidiyor. İşletim sistemleri (OS)