These samples show the usage of my two libraries, demonstrating how
it is possible to transfer images from PV to Windows and vice versa.
We show them too. Only a small part of the code is about data transfer
(that's what i wanted) the rest is about image handling... Cool things
always cost some effort ;)
PV will send the first Quick Memo it finds in its storage system,
be sure you have one image at least. VB will send the image whose
bitmap is contained in the file dance.dat. It is a text format,
produced by BmpTxt.exe tool contained in PV SDK, where i expanded
GSIZE macro. Complicated? It's just sample code.
Get yourselves a cup of coffee and let's get started...
Show PV Code
This manages the PV part of the system. AddButton is for the lazy
ones just like me ;) DoLoadQuickMemo contains some Storage system
stuff. CommCallback, DoReceive, DoSend are adsComm lib usage
samples.
#include <stdrom.h>
#include "define.h"
#include "libc.h"
#include "adsComm.h"
#define SCREEN_W 160
#define SCREEN_H 160
#define BTN_SND_X 60
#define BTN_SND_Y 20
#define BTN_SND_W 40
#define BTN_SND_H 12
#define BTN_SND_CAP "Send"
#define BTN_RCV_X 60
#define BTN_RCV_Y 40
#define BTN_RCV_W 40
#define BTN_RCV_H 12
#define BTN_RCV_CAP "Receive"
#define BTN_QUIT_X 60
#define BTN_QUIT_Y 80
#define BTN_QUIT_W 40
#define BTN_QUIT_H 12
#define BTN_QUIT_CAP "Quit"
#define BTN_ABORT_X 60
#define BTN_ABORT_Y 60
#define BTN_ABORT_W 40
#define BTN_ABORT_H 12
#define BTN_ABORT_CAP "Abort"
#define EVENT_TCH 1
#define EVENT_CRADLE 4
#define EVENT_BLD1 8
/**********************************************
Buffer and buffer size for data transfer
**********************************************/
#define BUFSIZE 3204
byte Buffer[BUFSIZE];
FILE_BUF fb;
void PollEvents(TCHSTS far *tsts, byte event_mask)
{
union REGS reg;
reg.x.ax = 0x0200 | event_mask;
reg.x.di = FP_OFF(tsts);
reg.x.es = FP_SEG(tsts);
int86(0x50, ®, ®);
}
/**********************************************
Button pushed/released animation
**********************************************/
void DoAnimate(int x1, int y1, int x2, int y2)
{
LibGdsReverse(x1, y1, x2, y2);
LibPutDispBox(x1, y1, x2 - x1, y2 - y1);
LibWait(IB_125MWAIT);
LibGdsReverse(x1, y1, x2, y2);
LibPutDispBox(x1, y1, x2 - x1, y2 - y1);
LibWait(IB_125MWAIT);
}
/**********************************************
Draws a button
**********************************************/
void AddButton(int BX, int BY, int BW, int BH, char *BCAP)
{
int sz;
LibGdsBox(BX, BY, BX + BW, BY + BH);
sz = LibGetProStrSize(IB_PFONT2, BCAP);
LibPutProStr(IB_PFONT2, BX + (BW - sz) / 2, BY + (BH - 7) / 2, BCAP, sz);
LibPutDispBox(BX, BY, BW + 1, BH + 1);
}
/**********************************************
tests if (px, py) is contained in (x, y, w, h)
**********************************************/
bool InRect(int px, int py, int x, int y, int w, int h)
{
return (x < px && px < x + w) && (y < py && py < y + h);
}
/**********************************************
Draws the buttons
**********************************************/
void RefreshDisplay()
{
LibClrDisp();
AddButton(BTN_RCV_X, BTN_RCV_Y,
BTN_RCV_W, BTN_RCV_H,
BTN_RCV_CAP);
AddButton(BTN_QUIT_X, BTN_QUIT_Y,
BTN_QUIT_W, BTN_QUIT_H,
BTN_QUIT_CAP);
AddButton(BTN_ABORT_X, BTN_ABORT_Y,
BTN_ABORT_W, BTN_ABORT_H,
BTN_ABORT_CAP);
AddButton(BTN_SND_X, BTN_SND_Y,
BTN_SND_W, BTN_SND_H,
BTN_SND_CAP);
LibPutDisp();
}
/**********************************************
Displays the image in "Buffer"
Exits when the screen is touched
**********************************************/
void DoViewer()
{
TCHSTS tsts;
bool bExit = FALSE;
int x, y, w, h;
w = *(word *) (Buffer + 0);
h = *(word *) (Buffer + 2);
if (w < 1 || w > 160 || h < 1 || h > 160)
{
LibPutMsgDlg("Can't display");
return;
}
x = (160 - w) / 2;
y = (160 - h) / 2;
LibOpenWindowS(OFF, 0, 0, 160, 160);
LibPutGraph(x, y, Buffer);
LibPutDispBox(x, y, x + 1, y + 1);
LibPutDisp();
LibWait(IB_500MWAIT);
for (;bExit == FALSE;)
{
PollEvents(&tsts, EVENT_TCH);
if (tsts.y != -1 || tsts.x != -1)
bExit = TRUE;
}
LibCloseWindow();
LibPutDisp();
}
/**********************************************
Fills the buffer with the first Quick Memo
it finds, no matter what subentry.
**********************************************/
bool DoLoadQuickMemo()
{
FILE_INFO fi;
fb.fsb_main_entry_ = 0xb0;
fb.fsb_scrt_info_ = 0x80;
fb.fsb_sub_entry_ = 0;
fi.fp = 0xFFFF;
fi.kind = FILE_KIND_BIN;
*(word *)(Buffer + 0) = 156;
*(word *)(Buffer + 2) = 130;
while (LibFileFindNext(&fb, &fi, 0x00))
{
if (LibFileRead(&fb, &fi))
{
memcpy(Buffer + 4, fb.fbuf.bin.bin_buf, 2600);
break;
}
else
return FALSE;
}
return TRUE;
}
/**********************************************
Communication callback function to have some
chance to abort
**********************************************/
bool CommCallback(byte status, word data)
{
TCHSTS tsts;
PollEvents(&tsts, EVENT_TCH);
if (tsts.y != -1 || tsts.x != -1)
if (InRect(tsts.x, tsts.y,
BTN_ABORT_X,
BTN_ABORT_Y,
BTN_ABORT_W,
BTN_ABORT_H))
return FALSE;
return TRUE;
}
/**********************************************
Waits for some data to be received and
stores it into "Buffer"
**********************************************/
bool DoReceive()
{
ADSCOMM_DATA data;
int res;
bool ret;
ret = FALSE;
data.Data = Buffer;
data.Size = BUFSIZE;
LibOpenWindowS(ON, 30, 100, 100, 50);
{
int sz;
sz = LibGetProStrSize(IB_PFONT1, "Receiving...");
LibPutProStr(IB_PFONT1, (160 - sz) / 2,
100 + 20, "Receiving...", sz);
}
LibPutDisp();
adsCommSetCallback(CommCallback);
if (!adsCommIsOpen())
adsCommOpen(IB_SRL_38400BPS);
res = adsCommRead(&data);
adsCommClose();
switch (res)
{
case ADSCOMM_SUCCESS:
LibPutMsgDlg("Success, %d bytes", data.Size);
ret = TRUE;
break;
case ADSCOMM_ERROR_DTE:
LibPutMsgDlg("Dte error");
break;
case ADSCOMM_ERROR_ABORT:
LibPutMsgDlg("Abort");
break;
};
LibCloseWindow();
LibPutDisp();
return ret;
}
/**********************************************
Sends BUFSIZE bytes through the serial cable
**********************************************/
bool DoSend()
{
ADSCOMM_DATA data;
int res;
bool ret;
ret = FALSE;
data.Data = Buffer;
data.Size = BUFSIZE;
LibOpenWindowS(ON, 30, 100, 100, 50);
{
int sz;
sz = LibGetProStrSize(IB_PFONT1, "Sending...");
LibPutProStr(IB_PFONT1, (160 - sz) / 2,
100 + 20, "Sending...", sz);
}
LibPutDisp();
adsCommSetCallback(CommCallback);
if (!adsCommIsOpen())
adsCommOpen(IB_SRL_38400BPS);
res = adsCommWrite(&data);
adsCommClose();
switch (res)
{
case ADSCOMM_SUCCESS:
LibPutMsgDlg("Success");
ret = TRUE;
break;
case ADSCOMM_ERROR_DTE:
LibPutMsgDlg("Dte error");
break;
case ADSCOMM_ERROR_ABORT:
LibPutMsgDlg("Abort");
break;
};
LibCloseWindow();
LibPutDisp();
return ret;
}
/**********************************************
Application events manager
**********************************************/
void main()
{
TCHSTS tsts;
bool bExit = FALSE;
RefreshDisplay();
for (;bExit == FALSE;)
{
PollEvents(&tsts, EVENT_TCH);
if (tsts.y != -1 || tsts.x != -1)
{
if (InRect(tsts.x, tsts.y,
BTN_RCV_X,
BTN_RCV_Y,
BTN_RCV_W,
BTN_RCV_H))
{
DoAnimate(BTN_RCV_X,
BTN_RCV_Y,
BTN_RCV_X + BTN_RCV_W,
BTN_RCV_Y + BTN_RCV_H);
if (DoReceive())
DoViewer();
RefreshDisplay();
}
if (InRect(tsts.x, tsts.y,
BTN_QUIT_X,
BTN_QUIT_Y,
BTN_QUIT_W,
BTN_QUIT_H))
{
DoAnimate(BTN_QUIT_X,
BTN_QUIT_Y,
BTN_QUIT_X + BTN_QUIT_W,
BTN_QUIT_Y + BTN_QUIT_H);
bExit = TRUE;
}
if (InRect(tsts.x, tsts.y,
BTN_SND_X,
BTN_SND_Y,
BTN_SND_W,
BTN_SND_H))
{
DoAnimate(BTN_SND_X,
BTN_SND_Y,
BTN_SND_X + BTN_SND_W,
BTN_SND_Y + BTN_SND_H);
DoLoadQuickMemo();
DoSend();
RefreshDisplay();
}
}
}
LibJumpMenu();
}
Show VB Code
Now don't get scared by this large number of new functions. Just
put them in a Module.bas file called, what can i say,
bitmap.bas and forget about them. These are Windows APIs we
need to import to show a Quick Memo on the PC.
Public Declare Function CreateBitmap Lib "gdi32" _
(ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal nPlanes As Long, ByVal nBitCount As Long, _
lpBits As Any) As Long
Public Declare Function CreateCompatibleDC Lib "gdi32" _
(ByVal hdc As Long) As Long
Public Declare Function GetDC Lib "user32" _
(ByVal hwnd As Long) As Long
Public Declare Function ReleaseDC Lib "user32" _
(ByVal hwnd As Long, ByVal hdc As Long) As Long
Public Declare Function SelectObject Lib "gdi32" _
(ByVal hdc As Long, ByVal hObject As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" _
(ByVal hObject As Long) As Long
Public Declare Function DeleteDC Lib "gdi32" _
(ByVal hdc As Long) As Long
Public Declare Function BitBlt Lib "gdi32" _
(ByVal hDestDC As Long, ByVal x As Long, _
ByVal y As Long, ByVal nWidth As Long, _
ByVal nHeight As Long, ByVal hSrcDC As Long, _
ByVal xSrc As Long, ByVal ySrc As Long, _
ByVal dwRop As Long) As Long
Public Declare Function SetBitmapBits Lib "gdi32" _
(ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
The application will send data contained in the following file, so
download it.
Download 'dance.dat'
Time to set up your VB form. Add:
Object | Name | Caption |
adsComm | adsComm1 | --- |
PictureBox | Picture1 | --- |
CommandButton | Send | Send |
CommandButton | Abort | Abort |
CommandButton | Receive | Receive |
Send_Click, Receive_Click, Abort_Click show how to use the
functions exported by our adsComm.ocx.
' TX stuff
Dim buffer() As Byte
Dim bufsize As Integer
' RX stuff
Dim bits(3000) As Byte
Dim hBmp As Long, old_hBmp As Long
Dim hDCImage As Long
' *************************************************************
' Image creation at start time
' *************************************************************
Private Sub Form_Load()
ImageSetup
End Sub
' *************************************************************
' Image clean up on quit
' *************************************************************
Private Sub Form_Unload(Cancel As Integer)
DeleteImage
End Sub
' *************************************************************
' Aborts the communication
' *************************************************************
Private Sub Abort_Click()
AdsComm1.Abort
End Sub
' *************************************************************
' Converts one digit from hex to dec
' *************************************************************
Private Function hex2dec(ByVal v As String) As Integer
v = Mid(v, 1, 1)
Select Case UCase(v)
Case "0" To "9"
hex2dec = Asc(v) - Asc("0")
Case "A" To "F"
hex2dec = Asc(v) - Asc("A") + 10
End Select
End Function
' *************************************************************
' Loads the image into "buffer"
' *************************************************************
Private Sub LoadImage()
Dim v As String
ReDim buffer(3) As Byte
Open "dance.dat" For Input As 1
Input #1, v
hi = hex2dec(Mid(v, 3, 1))
lo = hex2dec(Mid(v, 4, 1))
w = hi * 16 + lo
buffer(0) = w
Input #1, v ' unused, not that large
buffer(1) = 0
Input #1, v
hi = hex2dec(Mid(v, 3, 1))
lo = hex2dec(Mid(v, 4, 1))
h = hi * 16 + lo
buffer(2) = h
Input #1, v ' unused, not that large
buffer(3) = 0
n = Int((w + 7) / 8) * h
ReDim Preserve buffer(4 + n - 1) As Byte
bufsize = 4 + n
For i = 0 To n - 1
Input #1, v
If Trim(v) = "" Then Input #1, v
hi = hex2dec(Mid(v, 3, 1))
lo = hex2dec(Mid(v, 4, 1))
buffer(4 + i) = hi * 16 + lo
Next
Close 1
End Sub
' *************************************************************
' Sends "buffer" through the serial cable
' *************************************************************
Private Sub Send_Click()
LoadImage
If Not AdsComm1.IsCommOpen Then AdsComm1.CommOpen "38400"
res = AdsComm1.CommWrite(buffer, bufsize)
Select Case res
Case ADSCOMM_SUCCESS
MsgBox "Success"
Case ADSCOMM_ERROR_ABORT
MsgBox "Abort"
Case ADSCOMM_ERROR_DTE
MsgBox "Dte error"
Case ADSCOMM_ERROR_BREAK
MsgBox "break"
Case ADSCOMM_ERROR_PROTOCOL
MsgBox "Protocol error"
End Select
AdsComm1.CommClose
End Sub
' *************************************************************
' Receives bitmap bits and sets the image
' *************************************************************
Private Sub Receive_Click()
Dim Size As Integer
Size = 3000
If Not AdsComm1.IsCommOpen Then AdsComm1.CommOpen "38400"
res = AdsComm1.CommRead(bits, Size)
Select Case res
Case ADSCOMM_SUCCESS
r = SetBitmapBits(hBmp, 2600, bits(4))
Picture1.Refresh
'MsgBox "Success"
Case ADSCOMM_ERROR_ABORT
MsgBox "Abort"
Case ADSCOMM_ERROR_DTE
MsgBox "Dte error"
Case ADSCOMM_ERROR_BREAK
MsgBox "break"
Case ADSCOMM_ERROR_PROTOCOL
MsgBox "Protocol error"
End Select
AdsComm1.CommClose
End Sub
' *************************************************************
' Allocates a bitmap
' *************************************************************
Private Sub CreateImage()
hBmp = CreateBitmap(156, 130, 1, 1, bits(4))
hDCImage = CreateCompatibleDC(Form1.hdc)
old_hBmp = SelectObject(hDCImage, hBmp)
End Sub
' *************************************************************
' Image container setup
' *************************************************************
Private Sub ImageSetup()
hBmp = 0
Picture1.AutoRedraw = False
Picture1.ScaleMode = 3
Picture1.Height = Picture1.Width * 130 \ 156
Picture1.ScaleWidth = 156
Picture1.ScaleHeight = 130
CreateImage
For k = 0 To 2599: bits(k + 4) = 0: Next
SetBitmapBits hBmp, 2600, bits(4)
End Sub
' *************************************************************
' Time to redraw the image
' *************************************************************
Private Sub Picture1_Paint()
BitBlt Picture1.hdc, 0, 0, 156, 130, hDCImage, 0, 0, vbSrcCopy
End Sub
' *************************************************************
' Frees the bitmap resources
' *************************************************************
Private Sub DeleteImage()
SelectObject hDCImage, old_hBmp
DeleteObject hBmp
DeleteDC hDCImage
End Sub
|