15 Ağustos 2020 Cumartesi

QuickBasic - 20: Fare (mouse) kullanımı-1

Yayınlama: 29 Temmuz 2020
Güncelleme: 15 Ağustos 2020

Kötü haber: Qbasic ve QuickBasicte doğrudan fare(mouse) kullanmak için bir komut bulunmuyor.

Belkide Qbasic'in piyasaya sürüldüğü tarihlerde fare kullanımı yaygın değildi ya da fare standartları tam oturmamıştı.

İyi haber: QuickBasicte DOS kesintilerini(interrupt) çalıştırmak için ve assembly kodlarını belleğe aktarıp çalıştırmak için kodlar bulunuyor. Böylece dolaylı olarak da olsa fare kullanılabiliyor.

DOS kesintisi ile fare çalıştırma

DOS işletim sistemi yapısı gereği Windows gibi çoklu görev(multitasking) özelliği yoktur. DOS, kesinti denilen bir özelliği kullanarak sahte çoklu görev işlevini yerine getirir.

DOS/BIOS kesinti listelerine bakıldığında çok sayıda kesinti olduğu görülecektir.

Kesinti listesi: Link1, Link2, Link3, Link4, Link5, Link6

Bu yazının konusu olan ve bize gerekli olan kesinti &H33 (51)
&H33
kesintisi bilgisayar fare donanımı ile ilgi fonksiyonları içerir.
Kullanılacak fare fonksiyonunun numarası AX yazmacına(register) aktarılır.

Yazmaç(register) nedir?
Merkezi işlem biriminin(CPU = İşlemci) işlemleri daha hızlı yürütmek için kullandığı CPU içinde bulunan bellek birimleridir. Bu birim RAM belleğe göre daha hızlıdır.

Ön hazırlık

Kesinti kullanmadan önce QuickBasic'te bazı ön hazırlıklar yapmak gereklidir.

Bunlar:
1) QuickBasic editörünü komut satırından çalıştırılırken /L parametresi eklenerek çalıştırılır.
QB.EXE /L
Bu /L eklentisi LIB klasörü altında bulunan, belirtilmediğinde varsayılan kütüphane(library) olan QB.QLB dosyasını belleğe yükler.
Bu dosya, kesinti kullanımı için bize gerekli olan alt rutinleri(subroutine) içerir.

2) &H33 kesintisini oluşturmak için INTERRUPT alt programı çağıracağız.
Bu alt program QB.QLB ile belleğe yüklendi zaten. Yüklü olmadığı durumda "Subprogram not defined" (Alt program tanımlı değil) hatasını verir.

Kullanımı:
CALL INTERRUPT(kesintino, yazmaç_girdisi, yazmaç_çıktısı)
kesintino: Kullanılacak DOS kesinti numarası. Fare için &H33 kullanılacak.
yazmaç_girdisi: Yazmaçlara veri aktarmak için kullanılır.

Gerekli olan yazmaçları kullanmak için bir TYPE tanımlaması yapılmalıdır.
TYPE RegType
	ax    AS INTEGER
	bx    AS INTEGER
	cx    AS INTEGER
	dx    AS INTEGER
	bp    AS INTEGER
	si    AS INTEGER
	di    AS INTEGER
	flags AS INTEGER
END TYPE
Bu Regtype tanımlaması INC klasörü altında bulunan QB.BI dosyasında bulunmaktadır.

Üstteki kodları yazmak yerine QB.BI dosyasını INCLUDE komutu ile ekleyerek gerekli kodların yazacağımız programa dahil olmasını sağlayabiliriz.

QB.BI dosyanız yoksa buradan indirebilirsiniz.

Kullanımı:
'$INCLUDE: 'qb.bi'
Genelde bu kod satırı program kodlarının ilk satırına eklenir.
yazmaç_çıktısı: Yazmaç(register) değerlerini almak için kullanılır.
yazmaç_girdisi ve yazmaç_çıktısı RegType tipinde olmalıdır.

3) RegType tipinde yeni iki değişken tanımlaması yapılmalıdır.
DIM SHARED inreg AS RegType, outreg AS RegType
Üstteki satırla RegType tipinde inreg ve outreg değişkenleri oluşturulur. SHARED eklememizin sebebi değişkenin alt rutinlerde(SUB ve FUNCTION) de değerini koruması içindir.

4) Belleğe yüklenen INTERRUPT alt rutinini kullanacağımızı bildirmeliyiz.
DECLARE SUB INTERRUPT (intnum AS INTEGER, inreg AS RegType, outreg AS RegType)
Bu satır QB.BI içinde bulunduğu için bu satırı yazmamıza gerek yoktur. QB.BI kullanılmazsa gereklidir.

Fare kullanımı

Evet ön hazırlıklar tamam. Kodlamaya başlayalım.
Şimdiye kadar aşağıdaki satırları yazmış olmanız gerekir.
'$INCLUDE: 'qb.bi'
DIM SHARED inreg AS RegType, outreg AS RegType

Fare kurulu mu?

Sistemde fare takılı ve sürücüsü kurulu mu önce onu kontrol edelim.
Fare yok ise sonraki komutları çalıştırmamak gerekir.

AX yazmacına &H0 değeri aktarıp &H33 kesintisini çağırdığımızda AX yazmaç değeri &H0 ile dönerse fare yok ya da kurulmamış demektir.
0'dan farklı bir değer dönerse fare var demektir.

Fare varsa, kaç tuşlu olduğu dönen BX yazmacı ile öğrenilebilir.
Günümüzdeki fareler 3 veya daha fazla tuşlu olduğu için sonuç 3 çıkacaktır.
'$INCLUDE: 'qb.bi'
DIM SHARED inreg AS RegType, outreg AS RegType
inreg.ax = &H0
CALL INTERRUPT(&H33, inreg, outreg)
IF outreg.ax = &H0 THEN
	PRINT "Fare yok ya da kurulu değil!"
	END
ELSE
	PRINT "Fare var. Kullanılabilir."
END IF
PRINT "Tuş sayısı:"; outreg.bx

Fareyi sıfırla

Bu ve sonraki sayfada fare ile ilgili bazı ayarlamalar ve değişiklikler yapacağız.
Fare ayarlarında yapılan değişiklikleri(görünme, konum, hız, imleç, hassasiyet, vs.) sıfırlayıp varsayılana döndürmek için yine AX=&H0 kullanılır. Sonra kesinti çağrılır.
Bu işlem donanım ve yazılım sıfırlamasını gerçekleştirir. Yalnız yazılım sıfırlaması için: AX=&H21

Örnek 1:
inreg.ax = &H0 'fareyi sıfırla
CALL INTERRUPT(&H33, inreg, outreg)
Örnek 2:
inreg.ax = &H21 'yazılım sıfırlaması
CALL INTERRUPT(&H33, inreg, outreg)

Fare göster

Fare var. Kullanılabilir ancak ekranda görünmüyor değil mi?
Fareyi göstermek için AX yazmacını &H1'e eşitleyip kesintiyi çağırmak yeterli.
Üstteki kodların altına aşağıdaki satırları ekleyiniz.
inreg.ax = &H1 'fareyi göster
CALL INTERRUPT(&H33, inreg, outreg)
Kodlar çalıştırıldığında içi dolu dikdörtgen kutu simgeli ikonuyla fare görünecektir.

SCREEN 0 yazı ekranı olduğu için fare ikonu bu şekilde görünür. Grafik ekranda simgesi ok şeklindedir.

Fare gizle

Fareyi gizlemek gerekirse AX yazmacına &H2 değerini aktarıp kesintiyi çağırmak gerekir.
inreg.ax = &H2 'fareyi gizle
CALL INTERRUPT(&H33, inreg, outreg)
Fark ettiyseniz kesinti ve yazmaç değerleri 16'lık sayı sistemi(hexadecimal) ile kodlandı.

Bu şekilde olması şart değil. &H33 yerine 10'luk karşılığı olan 51 kullanılabilir ancak genel kullanım alışkanlığı bellek adresleri ve değerleri için 10'luk sayı sistemi yerine 16'lık sayı sistemini kullanmaktır.

Fare konumu

Farenin ekrandaki konumunu piksel(pixel=nokta) cinsinden almak için AX yazmacına &H3 değerini aktarıp kesintiyi çağırmak gerekir.

Kesinti sonrasında;
CX yazmacı farenin yatay(X) konumunu,
DX yazmacı farenin dikey(Y) konumunu verir.
Bu değerleri okumak için outreg değişkeni kullanılır. outreg dönüş değerleri içindir.

Kodlara aşağıdaki satırları ekleyin.
COLOR 12
DO
	inreg.ax = &H3 'fare koordinat bilgisi al
	CALL INTERRUPT(&H33, inreg, outreg)
	x = outreg.cx 'fare X konumu
	y = outreg.dx 'fare Y konumu
	LOCATE 3
	PRINT "X:"; x, "Y:"; y
LOOP UNTIL INKEY$ = CHR$(27)

Fare tuşların durumu

Tuşlara basıldığında BX yazmacının değeri değişir.
0 : Herhangi bir tuş basılı değil
1 : Sol fare tuşu basılı
2 : Sağ fare tuşu basılı
4 : Orta fare tuşu basılı

Aynı anda birden fazla tuşa basılırsa basılan tuşların değerleri toplamı BX değişkeninden okunabilir.
Örneğin Sol ve Sağ tuş aynı anda basılırsa 1+2 = 3 sonucu elde edilir.

Son girilen kodların yerine aşağıdaki kodları ekleyin.
SCREEN 12
inreg.ax = &H1 'fareyi göster
CALL INTERRUPT(&H33, inreg, outreg)
COLOR 10
DO
	inreg.ax = &H3 'fare koordinat bilgisi al
	CALL INTERRUPT(&H33, inreg, outreg)
	x = outreg.cx 'fare X konumu
	y = outreg.dx 'fare Y konumu
	LOCATE 1
	PRINT "X:"; x, "Y:"; y
	LOCATE 2
	PRINT "Tuş:"; outreg.bx
LOOP UNTIL INKEY$ = CHR$(27) 'ESC tuşu: Çıkış

Fare ile çizim yapma

' Fare ile grafik ekranda çizim
' ©2020 Mesut Akcan
' mesutakcan.blogspot.com
'$INCLUDE: 'qb.bi'
DEFINT A-Z
CLS
DIM SHARED inreg AS RegType, outreg AS RegType
inreg.ax = &H0
CALL INTERRUPT(&H33, inreg, outreg)
IF outreg.ax = &H0 THEN
	PRINT "Fare yok ya da kurulu değil!": END
END IF

SCREEN 12
inreg.ax = &H1 'fareyi göster
CALL INTERRUPT(&H33, inreg, outreg)
r = 14 'sarı renk
DO
	inreg.ax = &H3 'fare koordinat bilgisi al
	CALL INTERRUPT(&H33, inreg, outreg)
	x = outreg.cx 'fare X konumu
	y = outreg.dx 'fare Y konumu
	tus = outreg.bx 'tuş bilgisi al
	COLOR 10
	LOCATE 1: PRINT "Tuş:"; tus, "X:"; x, "Y:"; y,
	PRINT USING "Renk: ## "; r;
	COLOR r: PRINT STRING$(5, 219)
	SELECT CASE tus
		'Sol tuş basılı. Çizgi çiz
		CASE 1: LINE (px, py)-(x, y), r'son konum ile şimdiki konum
		CASE 2: CLS 'Sağ tuş basılı. Ekranı sil
		CASE 4: 'Orta tuş basılı. Renk belirle
			LOCATE 1
			INPUT "Çizim rengi (0-15):"; r
			IF r < 0 OR r > 15 THEN r = 15
	END SELECT
	px = x: py = y 'son konum
LOOP UNTIL INKEY$ = CHR$(27) 'ESC: çıkış

' Fare ile metin ekranda çizim
' ©2020 Mesut Akcan
' makcan@gmail.com
' mesutakcan.blogspot.com

' Sol tuş: Çizim
' Sağ tuş: Sil
' Orta tuş: Çizim karakteri ve rengi belirle
' ESC: Çıkış

DEFINT A-Z
'$INCLUDE: 'qb.bi'
DECLARE SUB Cerceve (en%, boy%)
DECLARE SUB KonumRenkYaz (yazi$, y%)
DECLARE SUB Kesinti ()
DECLARE SUB FareGoster ()
DECLARE SUB FareGizle ()
DIM SHARED inreg AS RegType, outreg AS RegType
inreg.ax = &H0
Kesinti
IF outreg.ax = &H0 THEN
	PRINT "Fare yok ya da kurulu değil!": END
END IF
SCREEN 0
WIDTH 80, 25
DEF SEG = &HB800 'Ekran bellek adresi
CLS
FareGoster
r = 15 'yazı rengi
asc2 = 219 'çizim ascii karakter kodu
DO
	inreg.ax = &H3 'fare koordinat bilgisi al
	Kesinti
	tus = outreg.bx 'tuş bilgisi al
	x = outreg.cx 'fare X konumu
	y = outreg.dx 'fare Y konumu
	str = y \ 8 + 1 'satır no
	stn = x \ 8 + 1 'sütun no
	LOCATE 1, 51
	KonumRenkYaz "Satır:", str
	KonumRenkYaz " Sütun:", stn
	KonumRenkYaz " Renk:", r
	COLOR r
	PRINT " "; STRING$(4, asc2)
	SELECT CASE tus
		CASE 1, 2: 'Sol veya sağ tuş basılı
			FareGizle
			bellek = ((str - 1) * 80 + stn - 1) * 2
			'sağ tuş ile sil
			IF tus = 1 THEN POKE bellek, asc2 ELSE POKE bellek, 32
			IF r > 15 THEN rt = r + &H70 ELSE rt = r 'yanıp sönen renkler
			POKE bellek + 1, rt ' PEEK(61)
			FareGoster
		CASE 4: 'Orta tuş basılı. Renk belirle
			FareGizle
			PCOPY 0, 1 'aktif ekranı 1 e kopyala
			Cerceve 33, 5
			LOCATE 12, 25
			LINE INPUT "Çizim renk kodu (0-31):"; crk$
			IF crk$ <> "" THEN
				rb = VAL(crk$) 'çizim renk kodu
				IF rb >= 0 AND rb <= 31 THEN r = rb
			END IF
			 
			LOCATE 13, 25
			LINE INPUT "Çizim karekter kodu (0-255):"; ckk$
			IF ckk$ <> "" THEN
				a2k = VAL(ckk$) 'çizim karakter kodu. ASCII
				IF a2k >= 0 AND a2k <= 255 THEN asc2 = a2k
			END IF
			PCOPY 1, 0 'kopyalan ekranı aktif ekrana aktar
			FareGoster
	END SELECT
LOOP UNTIL INKEY$ = CHR$(27) 'ESC: çıkış

SUB Cerceve (en, boy)
	zr = 3 'zemin rengi
	satir = (25 - boy) \ 2
	sutun = (80 - en) \ 2
	LOCATE satir, sutun
	COLOR 15, zr
	PRINT CHR$(218); : PRINT STRING$(en, 196); : COLOR 0: PRINT CHR$(191);
	FOR n = 1 TO boy
		COLOR 15: LOCATE satir + n, sutun: PRINT CHR$(179);
		COLOR , zr: PRINT STRING$(en, 255);
		COLOR 0: PRINT CHR$(179)
	NEXT
	COLOR 15: LOCATE satir + boy, sutun: PRINT CHR$(192);
	COLOR 0: PRINT STRING$(en, 196); CHR$(217);
END SUB

DEFSNG A-Z
SUB FareGizle
	inreg.ax = &H2 'fareyi gizle
	Kesinti
END SUB

SUB FareGoster
	inreg.ax = &H1 'fareyi göster
	Kesinti
END SUB

SUB Kesinti
	CALL INTERRUPT(&H33, inreg, outreg)
END SUB

SUB KonumRenkYaz (yazi$, y%)
	COLOR 7, 0: PRINT yazi$;
	COLOR 10: PRINT USING "##"; y%;
END SUB



Önceki Bölüm: 19: Grafik işlemleri-7 Sonraki Bölüm: 21: Fare (mouse) kullanımı-2

Hiç yorum yok:

Yorum Gönder