Как работать со сканером?
Как работать со сканером?
////////////////////////////////////////////////////////////////////////
////
// Delphi Scanner Support Framework //
// //
// Copyright (C) 1999 by Uli Tessel //
// //
////////////////////////////////////////////////////////////////////////
// //
// Modified and rewritten as a Delphi component by: //
// //
// M. de Haan //
// //
// June 2002 //
// //
////////////////////////////////////////////////////////////////////////
unit
TWAIN;
interface
uses
SysUtils, // Exceptions
Forms, // TMessageEvent
Windows, // HMODULE
Graphics, // TBitmap
IniFiles, // Inifile
Controls, // TCursor
Classes; // Class
const
// Messages
MSG_GET = $0001; // Get one or more values
MSG_GETCURRENT = $0002; // Get current value
MSG_GETDEFAULT = $0003; // Get default (e.g. power up) value
MSG_GETFIRST = $0004; // Get first of a series of items,
// e.g. Data Sources
MSG_GETNEXT = $0005; // Iterate through a series of items
MSG_SET = $0006; // Set one or more values
MSG_RESET = $0007; // Set current value to default value
MSG_QUERYSUPPORT = $0008; // Get supported operations on the
// capacities
// Messages used with DAT_NULL
// ---------------------------
MSG_XFERREADY = $0101; // The data source has data ready
MSG_CLOSEDSREQ = $0102; // Request for the application to close
// the Data Source
MSG_CLOSEDSOK = $0103; // Tell the application to save the
// state
MSG_DEVICEEVENT = $0104; // Some event has taken place
// Messages used with a pointer to a DAT_STATUS structure
// ------------------------------------------------------
MSG_CHECKSTATUS = $0201; // Get status information
// Messages used with a pointer to DAT_PARENT data
// -----------------------------------------------
MSG_OPENDSM = $0301; // Open the Data Source Manager
MSG_CLOSEDSM = $0302; // Close the Data Source Manager
// Messages used with a pointer to a DAT_IDENTITY structure
// --------------------------------------------------------
MSG_OPENDS = $0401; // Open a Data Source
MSG_CLOSEDS = $0402; // Close a Data Source
MSG_USERSELECT = $0403; // Put up a dialog of all Data Sources
// The user can select a Data Source
// Messages used with a pointer to a DAT_USERINTERFACE structure
// -------------------------------------------------------------
MSG_DISABLEDS = $0501; // Disable data transfer in the Data
// Source
MSG_ENABLEDS = $0502; // Enable data transfer in the Data
// Source
MSG_ENABLEDSUIONLY = $0503; // Enable for saving Data Source state
// only
// Messages used with a pointer to a DAT_EVENT structure
// -----------------------------------------------------
MSG_PROCESSEVENT = $0601;
// Messages used with a pointer to a DAT_PENDINGXFERS structure
// ------------------------------------------------------------
MSG_ENDXFER = $0701;
MSG_STOPFEEDER = $0702;
// Messages used with a pointer to a DAT_FILESYSTEM structure
// ----------------------------------------------------------
MSG_CHANGEDIRECTORY = $0801;
MSG_CREATEDIRECTORY = $0802;
MSG_DELETE = $0803;
MSG_FORMATMEDIA = $0804;
MSG_GETCLOSE = $0805;
MSG_GETFIRSTFILE = $0806;
MSG_GETINFO = $0807;
MSG_GETNEXTFILE = $0808;
MSG_RENAME = $0809;
MSG_COPY = $080A;
MSG_AUTOMATICCAPTUREDIRECTORY = $080B;
// Messages used with a pointer to a DAT_PASSTHRU structure
// --------------------------------------------------------
MSG_PASSTHRU = $0901;
const
DG_CONTROL = $0001; // data pertaining to control
DG_IMAGE = $0002; // data pertaining to raster images
const
// Data Argument Types for the DG_CONTROL Data Group.
DAT_CAPABILITY = $0001; // TW_CAPABILITY
DAT_EVENT = $0002; // TW_EVENT
DAT_IDENTITY = $0003; // TW_IDENTITY
DAT_PARENT = $0004; // TW_HANDLE,
// application win handle in Windows
DAT_PENDINGXFERS = $0005; // TW_PENDINGXFERS
DAT_SETUPMEMXFER = $0006; // TW_SETUPMEMXFER
DAT_SETUPFILEXFER = $0007; // TW_SETUPFILEXFER
DAT_STATUS = $0008; // TW_STATUS
DAT_USERINTERFACE = $0009; // TW_USERINTERFACE
DAT_XFERGROUP = $000A; // TW_UINT32
DAT_IMAGEMEMXFER = $0103; // TW_IMAGEMEMXFER
DAT_IMAGENATIVEXFER = $0104; // TW_UINT32, loword is hDIB, PICHandle
DAT_IMAGEFILEXFER = $0105; // Null data
const
// Condition Codes: Application gets these by doing DG_CONTROL
// DAT_STATUS MSG_GET.
TWCC_CUSTOMBASE = $8000;
TWCC_SUCCESS = 00; // It worked!
TWCC_BUMMER = 01; // Failure due to unknown causes
TWCC_LOWMEMORY = 02; // Not enough memory to perform operation
TWCC_NODS = 03; // No Data Source
TWCC_MAXCONNECTIONS = 04; // Data Source is connected to maximum
// number of possible applications
TWCC_OPERATIONERROR = 05; // Data Source or Data Source Manager
// reported error, application
// shouldn't report an error
TWCC_BADCAP = 06; // Unknown capability
TWCC_BADPROTOCOL = 09; // Unrecognized MSG DG DAT combination
TWCC_BADVALUE = 10; // Data parameter out of range
TWCC_SEQERROR = 11; // DG DAT MSG out of expected sequence
TWCC_BADDEST = 12; // Unknown destination Application /
// Source in DSM_Entry
TWCC_CAPUNSUPPORTED = 13; // Capability not supported by source
TWCC_CAPBADOPERATION = 14; // Operation not supported by
// capability
TWCC_CAPSEQERROR = 15; // Capability has dependancy on other
// capability
TWCC_DENIED = 16; // File System operation is denied
// (file is protected)
TWCC_FILEEXISTS = 17; // Operation failed because file
// already exists
TWCC_FILENOTFOUND = 18; // File not found
TWCC_NOTEMPTY = 19; // Operation failed because directory
// is not empty
TWCC_PAPERJAM = 20; // The feeder is jammed
TWCC_PAPERDOUBLEFEED = 21; // The feeder detected multiple pages
TWCC_FILEWRITEERROR = 22; // Error writing the file (meant for
// things like disk full conditions)
TWCC_CHECKDEVICEONLINE = 23; // The device went offline prior to or
// during this operation
const
// Flags used in TW_MEMORY structure
TWMF_APPOWNS = $01;
TWMF_DSMOWNS = $02;
TWMF_DSOWNS = $04;
TWMF_POINTER = $08;
TWMF_HANDLE = $10;
const
// Flags for country, which seems to be equal to their telephone
// number
TWCY_AFGHANISTAN = 1001;
TWCY_ALGERIA = 0213;
TWCY_AMERICANSAMOA = 0684;
TWCY_ANDORRA = 0033;
TWCY_ANGOLA = 1002;
TWCY_ANGUILLA = 8090;
TWCY_ANTIGUA = 8091;
TWCY_ARGENTINA = 0054;
TWCY_ARUBA = 0297;
TWCY_ASCENSIONI = 0247;
TWCY_AUSTRALIA = 0061;
TWCY_AUSTRIA = 0043;
TWCY_BAHAMAS = 8092;
TWCY_BAHRAIN = 0973;
TWCY_BANGLADESH = 0880;
TWCY_BARBADOS = 8093;
TWCY_BELGIUM = 0032;
TWCY_BELIZE = 0501;
TWCY_BENIN = 0229;
TWCY_BERMUDA = 8094;
TWCY_BHUTAN = 1003;
TWCY_BOLIVIA = 0591;
TWCY_BOTSWANA = 0267;
TWCY_BRITAIN = 0006;
TWCY_BRITVIRGINIS = 8095;
TWCY_BRAZIL = 0055;
TWCY_BRUNEI = 0673;
TWCY_BULGARIA = 0359;
TWCY_BURKINAFASO = 1004;
TWCY_BURMA = 1005;
TWCY_BURUNDI = 1006;
TWCY_CAMAROON = 0237;
TWCY_CANADA = 0002;
TWCY_CAPEVERDEIS = 0238;
TWCY_CAYMANIS = 8096;
TWCY_CENTRALAFREP = 1007;
TWCY_CHAD = 1008;
TWCY_CHILE = 0056;
TWCY_CHINA = 0086;
TWCY_CHRISTMASIS = 1009;
TWCY_COCOSIS = 1009;
TWCY_COLOMBIA = 0057;
TWCY_COMOROS = 1010;
TWCY_CONGO = 1011;
TWCY_COOKIS = 1012;
TWCY_COSTARICA = 0506;
TWCY_CUBA = 0005;
TWCY_CYPRUS = 0357;
TWCY_CZECHOSLOVAKIA = 0042;
TWCY_DENMARK = 0045;
TWCY_DJIBOUTI = 1013;
TWCY_DOMINICA = 8097;
TWCY_DOMINCANREP = 8098;
TWCY_EASTERIS = 1014;
TWCY_ECUADOR = 0593;
TWCY_EGYPT = 0020;
TWCY_ELSALVADOR = 0503;
TWCY_EQGUINEA = 1015;
TWCY_ETHIOPIA = 0251;
TWCY_FALKLANDIS = 1016;
TWCY_FAEROEIS = 0298;
TWCY_FIJIISLANDS = 0679;
TWCY_FINLAND = 0358;
TWCY_FRANCE = 0033;
TWCY_FRANTILLES = 0596;
TWCY_FRGUIANA = 0594;
TWCY_FRPOLYNEISA = 0689;
TWCY_FUTANAIS = 1043;
TWCY_GABON = 0241;
TWCY_GAMBIA = 0220;
TWCY_GERMANY = 0049;
TWCY_GHANA = 0233;
TWCY_GIBRALTER = 0350;
TWCY_GREECE = 0030;
TWCY_GREENLAND = 0299;
TWCY_GRENADA = 8099;
TWCY_GRENEDINES = 8015;
TWCY_GUADELOUPE = 0590;
TWCY_GUAM = 0671;
TWCY_GUANTANAMOBAY = 5399;
TWCY_GUATEMALA = 0502;
TWCY_GUINEA = 0224;
TWCY_GUINEABISSAU = 1017;
TWCY_GUYANA = 0592;
TWCY_HAITI = 0509;
TWCY_HONDURAS = 0504;
TWCY_HONGKONG = 0852;
TWCY_HUNGARY = 0036;
TWCY_ICELAND = 0354;
TWCY_INDIA = 0091;
TWCY_INDONESIA = 0062;
TWCY_IRAN = 0098;
TWCY_IRAQ = 0964;
TWCY_IRELAND = 0353;
TWCY_ISRAEL = 0972;
TWCY_ITALY = 0039;
TWCY_IVORYCOAST = 0225;
TWCY_JAMAICA = 8010;
TWCY_JAPAN = 0081;
TWCY_JORDAN = 0962;
TWCY_KENYA = 0254;
TWCY_KIRIBATI = 1018;
TWCY_KOREA = 0082;
TWCY_KUWAIT = 0965;
TWCY_LAOS = 1019;
TWCY_LEBANON = 1020;
TWCY_LIBERIA = 0231;
TWCY_LIBYA = 0218;
TWCY_LIECHTENSTEIN = 0041;
TWCY_LUXENBOURG = 0352;
TWCY_MACAO = 0853;
TWCY_MADAGASCAR = 1021;
TWCY_MALAWI = 0265;
TWCY_MALAYSIA = 0060;
TWCY_MALDIVES = 0960;
TWCY_MALI = 1022;
TWCY_MALTA = 0356;
TWCY_MARSHALLIS = 0692;
TWCY_MAURITANIA = 1023;
TWCY_MAURITIUS = 0230;
TWCY_MEXICO = 0003;
TWCY_MICRONESIA = 0691;
TWCY_MIQUELON = 0508;
TWCY_MONACO = 0033;
TWCY_MONGOLIA = 1024;
TWCY_MONTSERRAT = 8011;
TWCY_MOROCCO = 0212;
TWCY_MOZAMBIQUE = 1025;
TWCY_NAMIBIA = 0264;
TWCY_NAURU = 1026;
TWCY_NEPAL = 0977;
TWCY_NETHERLANDS = 0031;
TWCY_NETHANTILLES = 0599;
TWCY_NEVIS = 8012;
TWCY_NEWCALEDONIA = 0687;
TWCY_NEWZEALAND = 0064;
TWCY_NICARAGUA = 0505;
TWCY_NIGER = 0227;
TWCY_NIGERIA = 0234;
TWCY_NIUE = 1027;
TWCY_NORFOLKI = 1028;
TWCY_NORWAY = 0047;
TWCY_OMAN = 0968;
TWCY_PAKISTAN = 0092;
TWCY_PALAU = 1029;
TWCY_PANAMA = 0507;
TWCY_PARAGUAY = 0595;
TWCY_PERU = 0051;
TWCY_PHILLIPPINES = 0063;
TWCY_PITCAIRNIS = 1030;
TWCY_PNEWGUINEA = 0675;
TWCY_POLAND = 0048;
TWCY_PORTUGAL = 0351;
TWCY_QATAR = 0974;
TWCY_REUNIONI = 1031;
TWCY_ROMANIA = 0040;
TWCY_RWANDA = 0250;
TWCY_SAIPAN = 0670;
TWCY_SANMARINO = 0039;
TWCY_SAOTOME = 1033;
TWCY_SAUDIARABIA = 0966;
TWCY_SENEGAL = 0221;
TWCY_SEYCHELLESIS = 1034;
TWCY_SIERRALEONE = 1035;
TWCY_SINGAPORE = 0065;
TWCY_SOLOMONIS = 1036;
TWCY_SOMALI = 1037;
TWCY_SOUTHAFRICA = 0027;
TWCY_SPAIN = 0034;
TWCY_SRILANKA = 0094;
TWCY_STHELENA = 1032;
TWCY_STKITTS = 8013;
TWCY_STLUCIA = 8014;
TWCY_STPIERRE = 0508;
TWCY_STVINCENT = 8015;
TWCY_SUDAN = 1038;
TWCY_SURINAME = 0597;
TWCY_SWAZILAND = 0268;
TWCY_SWEDEN = 0046;
TWCY_SWITZERLAND = 0041;
TWCY_SYRIA = 1039;
TWCY_TAIWAN = 0886;
TWCY_TANZANIA = 0255;
TWCY_THAILAND = 0066;
TWCY_TOBAGO = 8016;
TWCY_TOGO = 0228;
TWCY_TONGAIS = 0676;
TWCY_TRINIDAD = 8016;
TWCY_TUNISIA = 0216;
TWCY_TURKEY = 0090;
TWCY_TURKSCAICOS = 8017;
TWCY_TUVALU = 1040;
TWCY_UGANDA = 0256;
TWCY_USSR = 0007;
TWCY_UAEMIRATES = 0971;
TWCY_UNITEDKINGDOM = 0044;
TWCY_USA = 0001;
TWCY_URUGUAY = 0598;
TWCY_VANUATU = 1041;
TWCY_VATICANCITY = 0039;
TWCY_VENEZUELA = 0058;
TWCY_WAKE = 1042;
TWCY_WALLISIS = 1043;
TWCY_WESTERNSAHARA = 1044;
TWCY_WESTERNSAMOA = 1045;
TWCY_YEMEN = 1046;
TWCY_YUGOSLAVIA = 0038;
TWCY_ZAIRE = 0243;
TWCY_ZAMBIA = 0260;
TWCY_ZIMBABWE = 0263;
TWCY_ALBANIA = 0355;
TWCY_ARMENIA = 0374;
TWCY_AZERBAIJAN = 0994;
TWCY_BELARUS = 0375;
TWCY_BOSNIAHERZGO = 0387;
TWCY_CAMBODIA = 0855;
TWCY_CROATIA = 0385;
TWCY_CZECHREPUBLIC = 0420;
TWCY_DIEGOGARCIA = 0246;
TWCY_ERITREA = 0291;
TWCY_ESTONIA = 0372;
TWCY_GEORGIA = 0995;
TWCY_LATVIA = 0371;
TWCY_LESOTHO = 0266;
TWCY_LITHUANIA = 0370;
TWCY_MACEDONIA = 0389;
TWCY_MAYOTTEIS = 0269;
TWCY_MOLDOVA = 0373;
TWCY_MYANMAR = 0095;
TWCY_NORTHKOREA = 0850;
TWCY_PUERTORICO = 0787;
TWCY_RUSSIA = 0007;
TWCY_SERBIA = 0381;
TWCY_SLOVAKIA = 0421;
TWCY_SLOVENIA = 0386;
TWCY_SOUTHKOREA = 0082;
TWCY_UKRAINE = 0380;
TWCY_USVIRGINIS = 0340;
TWCY_VIETNAM = 0084;
const
// Flags for languages
TWLG_DAN = 000; // Danish
TWLG_DUT = 001; // Dutch
TWLG_ENG = 002; // English
TWLG_FCF = 003; // French Canadian
TWLG_FIN = 004; // Finnish
TWLG_FRN = 005; // French
TWLG_GER = 006; // German
TWLG_ICE = 007; // Icelandic
TWLG_ITN = 008; // Italian
TWLG_NOR = 009; // Norwegian
TWLG_POR = 010; // Portuguese
TWLG_SPA = 011; // Spannish
TWLG_SWE = 012; // Swedish
TWLG_USA = 013;
TWLG_AFRIKAANS = 014;
TWLG_ALBANIA = 015;
TWLG_ARABIC = 016;
TWLG_ARABIC_ALGERIA = 017;
TWLG_ARABIC_BAHRAIN = 018;
TWLG_ARABIC_EGYPT = 019;
TWLG_ARABIC_IRAQ = 020;
TWLG_ARABIC_JORDAN = 021;
TWLG_ARABIC_KUWAIT = 022;
TWLG_ARABIC_LEBANON = 023;
TWLG_ARABIC_LIBYA = 024;
TWLG_ARABIC_MOROCCO = 025;
TWLG_ARABIC_OMAN = 026;
TWLG_ARABIC_QATAR = 027;
TWLG_ARABIC_SAUDIARABIA = 028;
TWLG_ARABIC_SYRIA = 029;
TWLG_ARABIC_TUNISIA = 030;
TWLG_ARABIC_UAE = 031; // United Arabic Emirates
TWLG_ARABIC_YEMEN = 032;
TWLG_BASQUE = 033;
TWLG_BYELORUSSIAN = 034;
TWLG_BULGARIAN = 035;
TWLG_CATALAN = 036;
TWLG_CHINESE = 037;
TWLG_CHINESE_HONGKONG = 038;
TWLG_CHINESE_PRC = 039; // People's Republic of China
TWLG_CHINESE_SINGAPORE = 040;
TWLG_CHINESE_SIMPLIFIED = 041;
TWLG_CHINESE_TAIWAN = 042;
TWLG_CHINESE_TRADITIONAL = 043;
TWLG_CROATIA = 044;
TWLG_CZECH = 045;
TWLG_DANISH = TWLG_DAN;
TWLG_DUTCH = TWLG_DUT;
TWLG_DUTCH_BELGIAN = 046;
TWLG_ENGLISH = TWLG_ENG;
TWLG_ENGLISH_AUSTRALIAN = 047;
TWLG_ENGLISH_CANADIAN = 048;
TWLG_ENGLISH_IRELAND = 049;
TWLG_ENGLISH_NEWZEALAND = 050;
TWLG_ENGLISH_SOUTHAFRICA = 051;
TWLG_ENGLISH_UK = 052;
TWLG_ENGLISH_USA = TWLG_USA;
TWLG_ESTONIAN = 053;
TWLG_FAEROESE = 054;
TWLG_FARSI = 055;
TWLG_FINNISH = TWLG_FIN;
TWLG_FRENCH = TWLG_FRN;
TWLG_FRENCH_BELGIAN = 056;
TWLG_FRENCH_CANADIAN = TWLG_FCF;
TWLG_FRENCH_LUXEMBOURG = 057;
TWLG_FRENCH_SWISS = 058;
TWLG_GERMAN = TWLG_GER;
TWLG_GERMAN_AUSTRIAN = 059;
TWLG_GERMAN_LUXEMBOURG = 060;
TWLG_GERMAN_LIECHTENSTEIN = 061;
TWLG_GERMAN_SWISS = 062;
TWLG_GREEK = 063;
TWLG_HEBREW = 064;
TWLG_HUNGARIAN = 065;
TWLG_ICELANDIC = TWLG_ICE;
TWLG_INDONESIAN = 066;
TWLG_ITALIAN = TWLG_ITN;
TWLG_ITALIAN_SWISS = 067;
TWLG_JAPANESE = 068;
TWLG_KOREAN = 069;
TWLG_KOREAN_JOHAB = 070;
TWLG_LATVIAN = 071;
TWLG_LITHUANIAN = 072;
TWLG_NORWEGIAN = TWLG_NOR;
TWLG_NORWEGIAN_BOKMAL = 073;
TWLG_NORWEGIAN_NYNORSK = 074;
TWLG_POLISH = 075;
TWLG_PORTUGUESE = TWLG_POR;
TWLG_PORTUGUESE_BRAZIL = 076;
TWLG_ROMANIAN = 077;
TWLG_RUSSIAN = 078;
TWLG_SERBIAN_LATIN = 079;
TWLG_SLOVAK = 080;
TWLG_SLOVENIAN = 081;
TWLG_SPANISH = TWLG_SPA;
TWLG_SPANISH_MEXICAN = 082;
TWLG_SPANISH_MODERN = 083;
TWLG_SWEDISH = TWLG_SWE;
TWLG_THAI = 084;
TWLG_TURKISH = 085;
TWLG_UKRANIAN = 086;
TWLG_ASSAMESE = 087;
TWLG_BENGALI = 088;
TWLG_BIHARI = 089;
TWLG_BODO = 090;
TWLG_DOGRI = 091;
TWLG_GUJARATI = 092;
TWLG_HARYANVI = 093;
TWLG_HINDI = 094;
TWLG_KANNADA = 095;
TWLG_KASHMIRI = 096;
TWLG_MALAYALAM = 097;
TWLG_MARATHI = 098;
TWLG_MARWARI = 099;
TWLG_MEGHALAYAN = 100;
TWLG_MIZO = 101;
TWLG_NAGA = 102;
TWLG_ORISSI = 103;
TWLG_PUNJABI = 104;
TWLG_PUSHTU = 105;
TWLG_SERBIAN_CYRILLIC = 106;
TWLG_SIKKIMI = 107;
TWLG_SWEDISH_FINLAND = 108;
TWLG_TAMIL = 109;
TWLG_TELUGU = 110;
TWLG_TRIPURI = 111;
TWLG_URDU = 112;
TWLG_VIETNAMESE = 113;
const
TWRC_SUCCESS = 0;
TWRC_FAILURE = 1; // Application may get TW_STATUS for
// info on failure
TWRC_CHECKSTATUS = 2; // tried hard to get the status
TWRC_CANCEL = 3;
TWRC_DSEVENT = 4;
TWRC_NOTDSEVENT = 5;
TWRC_XFERDONE = 6;
TWRC_ENDOFLIST = 7; // After MSG_GETNEXT if nothing left
TWRC_INFONOTSUPPORTED = 8;
TWRC_DATANOTAVAILABLE = 9;
const
TWON_ONEVALUE = $05; // indicates TW_ONEVALUE container
TWON_DONTCARE8 = $FF;
const
ICAP_XFERMECH = $0103;
const
TWTY_UINT16 = $0004; // Means: item is a TW_UINT16
const
// ICAP_XFERMECH values (SX_ means Setup XFer)
TWSX_NATIVE = 0;
TWSX_FILE = 1;
TWSX_MEMORY = 2;
TWSX_FILE2 = 3;
type
TW_UINT16 = WORD; // unsigned short TW_UINT16
pTW_UINT16 = ^TW_UINT16;
TTWUInt16 = TW_UINT16;
PTWUInt16 = pTW_UINT16;
type
TW_BOOL = WORDBOOL; // unsigned short TW_BOOL
pTW_BOOL = ^TW_BOOL;
TTWBool = TW_BOOL;
PTWBool = pTW_BOOL;
type
TW_STR32 = array[0..33] of Char; // char TW_STR32[34]
pTW_STR32 = ^TW_STR32;
TTWStr32 = TW_STR32;
PTWStr32 = pTW_STR32;
type
TW_STR255 = array[0..255] of Char; // char TW_STR255[256]
pTW_STR255 = ^TW_STR255;
TTWStr255 = TW_STR255;
PTWStr255 = pTW_STR255;
type
TW_INT16 = SmallInt; // short TW_INT16
pTW_INT16 = ^TW_INT16;
TTWInt16 = TW_INT16;
PTWInt16 = pTW_INT16;
type
TW_UINT32 = ULONG; // unsigned long TW_UINT32
pTW_UINT32 = ^TW_UINT32;
TTWUInt32 = TW_UINT32;
PTWUInt32 = pTW_UINT32;
type
TW_HANDLE = THandle;
TTWHandle = TW_HANDLE;
TW_MEMREF = Pointer;
TTWMemRef = TW_MEMREF;
type
// DAT_PENDINGXFERS. Used with MSG_ENDXFER to indicate additional
// data
TW_PENDINGXFERS = packed record
Count: TW_UINT16;
case Boolean of
False: (EOJ: TW_UINT32);
True: (Reserved: TW_UINT32);
end;
pTW_PENDINGXFERS = ^TW_PENDINGXFERS;
TTWPendingXFERS = TW_PENDINGXFERS;
PTWPendingXFERS = pTW_PENDINGXFERS;
type
// DAT_EVENT. For passing events down from the application to the DS
TW_EVENT = packed record
pEvent: TW_MEMREF; // Windows pMSG or Mac pEvent.
TWMessage: TW_UINT16; // TW msg from data source, e.g.
// MSG_XFERREADY
end;
pTW_EVENT = ^TW_EVENT;
TTWEvent = TW_EVENT;
PTWEvent = pTW_EVENT;
type
// TWON_ONEVALUE. Container for one value
TW_ONEVALUE = packed record
ItemType: TW_UINT16;
Item: TW_UINT32;
end;
pTW_ONEVALUE = ^TW_ONEVALUE;
TTWOneValue = TW_ONEVALUE;
PTWOneValue = pTW_ONEVALUE;
type
// DAT_CAPABILITY. Used by application to get/set capability from/in
// a data source.
TW_CAPABILITY = packed record
Cap: TW_UINT16; // id of capability to set or get, e.g.
// CAP_BRIGHTNESS
ConType: TW_UINT16; // TWON_ONEVALUE, _RANGE, _ENUMERATION or
// _ARRAY
hContainer: TW_HANDLE; // Handle to container of type Dat
end;
pTW_CAPABILITY = ^TW_CAPABILITY;
TTWCapability = TW_CAPABILITY;
PTWCapability = pTW_CAPABILITY;
type
// DAT_STATUS. Application gets detailed status info from a data
// source with this
TW_STATUS = packed record
ConditionCode: TW_UINT16; // Any TWCC_xxx constant
Reserved: TW_UINT16; // Future expansion space
end;
pTW_STATUS = ^TW_STATUS;
TTWStatus = TW_STATUS;
PTWStatus = pTW_STATUS;
type
// No DAT needed. Used to manage memory buffers
TW_MEMORY = packed record
Flags: TW_UINT32; // Any combination of the TWMF_ constants
Length: TW_UINT32; // Number of bytes stored in buffer TheMem
TheMem: TW_MEMREF; // Pointer or handle to the allocated memory
// buffer
end;
pTW_MEMORY = ^TW_MEMORY;
TTWMemory = TW_MEMORY;
PTWMemory = pTW_MEMORY;
const
// ICAP_IMAGEFILEFORMAT values (FF_means File Format
TWFF_TIFF = 0; // Tagged Image File Format
TWFF_PICT = 1; // Macintosh PICT
TWFF_BMP = 2; // Windows Bitmap
TWFF_XBM = 3; // X-Windows Bitmap
TWFF_JFIF = 4; // JPEG File Interchange Format
TWFF_FPX = 5; // Flash Pix
TWFF_TIFFMULTI = 6; // Multi-page tiff file
TWFF_PNG = 7; // Portable Network Graphic
TWFF_SPIFF = 8;
TWFF_EXIF = 9;
type
// DAT_SETUPFILEXFER. Sets up DS to application data transfer via a
// file
TW_SETUPFILEXFER = packed record
FileName: TW_STR255;
Format: TW_UINT16; // Any TWFF_xxx constant
VRefNum: TW_INT16; // Used for Mac only
end;
pTW_SETUPFILEXFER = ^TW_SETUPFILEXFER;
TTWSetupFileXFER = TW_SETUPFILEXFER;
PTWSetupFileXFER = pTW_SETUPFILEXFER;
type
// DAT_SETUPFILEXFER2. Sets up DS to application data transfer via a
// file. }
TW_SETUPFILEXFER2 = packed record
FileName: TW_MEMREF; // Pointer to file name text
FileNameType: TW_UINT16; // TWTY_STR1024 or TWTY_UNI512
Format: TW_UINT16; // Any TWFF_xxx constant
VRefNum: TW_INT16; // Used for Mac only
parID: TW_UINT32; // Used for Mac only
end;
pTW_SETUPFILEXFER2 = ^TW_SETUPFILEXFER2;
TTWSetupFileXFER2 = TW_SETUPFILEXFER2;
PTWSetupFileXFER2 = pTW_SETUPFILEXFER2;
type
// DAT_SETUPMEMXFER. Sets up Data Source to application data
// transfer via a memory buffer
TW_SETUPMEMXFER = packed record
MinBufSize: TW_UINT32;
MaxBufSize: TW_UINT32;
Preferred: TW_UINT32;
end;
pTW_SETUPMEMXFER = ^TW_SETUPMEMXFER;
TTWSetupMemXFER = TW_SETUPMEMXFER;
PTWSetupMemXFER = pTW_SETUPMEMXFER;
type
TW_VERSION = packed record
MajorNum: TW_UINT16; // Major revision number of the software.
MinorNum: TW_UINT16; // Incremental revision number of the
// software
Language: TW_UINT16; // e.g. TWLG_SWISSFRENCH
Country: TW_UINT16; // e.g. TWCY_SWITZERLAND
Info: TW_STR32; // e.g. "1.0b3 Beta release"
end;
pTW_VERSION = ^TW_VERSION;
PTWVersion = pTW_VERSION;
TTWVersion = TW_VERSION;
type
TW_IDENTITY = packed record
Id: TW_UINT32; // Unique number. In Windows,
// application hWnd
Version: TW_VERSION; // Identifies the piece of code
ProtocolMajor: TW_UINT16; // Application and DS must set to
// TWON_PROTOCOLMAJOR
ProtocolMinor: TW_UINT16; // Application and DS must set to
// TWON_PROTOCOLMINOR
SupportedGroups: TW_UINT32; // Bit field OR combination of DG_
// constants
Manufacturer: TW_STR32; // Manufacturer name, e.g.
// "Hewlett-Packard"
ProductFamily: TW_STR32; // Product family name, e.g.
// "ScanJet"
ProductName: TW_STR32; // Product name, e.g. "ScanJet Plus"
end;
pTW_IDENTITY = ^TW_IDENTITY;
type
// DAT_USERINTERFACE. Coordinates UI between application and data
// source
TW_USERINTERFACE = packed record
ShowUI: TW_BOOL; // TRUE if DS should bring up its UI
ModalUI: TW_BOOL; // For Mac only - true if the DS's UI is modal
hParent: TW_HANDLE; // For Windows only - Application handle
end;
pTW_USERINTERFACE = ^TW_USERINTERFACE;
TTWUserInterface = TW_USERINTERFACE;
PTWUserInterface = pTW_USERINTERFACE;
////////////////////////////////////////////////////////////////////////
// //
// END OF TWAIN TYPES AND CONSTANTS //
// //
////////////////////////////////////////////////////////////////////////
const
TWAIN_DLL_Name = 'TWAIN_32.DLL';
DSM_Entry_Name = 'DSM_Entry';
Ini_File_Name = 'WIN.INI';
CrLf = #13 + #10;
resourcestring // Errorstrings:
ERR_DSM_ENTRY_NOT_FOUND = 'Unable to find the entry of the Data ' +
'Source Manager in: TWAIN_32.DLL';
ERR_TWAIN_NOT_LOADED = 'Unable to load or find: TWAIN_32.DLL';
ERR_DSM_CALL_FAILED = 'A call to the Data Source Manager failed ' +
'in module %s';
ERR_UNKNOWN = 'A call to the Data Source Manager failed ' +
'in module %s: Code %.04x';
ERR_DSM_OPEN = 'Unable to close the Data Source Manager. ' +
'Maybe a source is still in use';
ERR_STATUS = 'Unable to get the status';
ERR_DSM = 'Data Source Manager error in module %s:' +
CrLf + '%s';
ERR_DS = 'Data Source error in module %s:' +
CrLf + '%s';
type
ETwainError = class(Exception);
TImageType = (ffTIFF, ffPICT, ffBMP, ffXBM, ffJFIF, ffFPX,
ffTIFFMULTI, ffPNG, ffSPIFF, ffEXIF, ffUNKNOWN);
TTransferType = (xfNative, xfMemory, xfFile);
TLanguageType = (lgDutch, lgEnglish,
lgFrench, lgGerman,
lgAmerican, lgItalian,
lgSpanish, lgNorwegian,
lgFinnish, lgDanish,
lgRussian, lgPortuguese,
lgSwedish, lgPolish,
lgGreek, lgTurkish);
TCountryType = (ctNetherlands, ctEngland,
ctFrance, ctGermany,
ctUSA, ctSpain,
ctItaly, ctDenmark,
ctFinland, ctNorway,
ctRussia, ctPortugal,
ctSweden, ctPoland,
ctGreece, ctTurkey);
TTWAIN = class(TComponent)
private
// Private declarations
fBitmap: TBitmap; // the actual bmp used for
// scanning, must be
// removed
HDSMDLL: HMODULE; // = 0, the library handle:
// will stay global
appId: TW_IDENTITY; // our (Application) ID.
// (may stay global)
dsId: TW_IDENTITY; // Data Source ID (will
// become member of DS
// class)
fhWnd: HWND; // = 0, maybe will be
// removed, use
// application.handle
// instead
fXfer: TTransferType; // = xfNative;
bDataSourceManagerOpen: Boolean; // = False, flag, may stay
// global
bDataSourceOpen: Boolean; // = False, will become
// member of DS class
bDataSourceEnabled: Boolean; // = False, will become
// member of DS class
fScanReady: TNotifyEvent; // notifies that the scan
// is ready
sDefaultSource: string; // remember old data source
fOldOnMessageHandler: TMessageEvent; // Save old OnMessage event
fShowUI: Boolean; // Show User Interface
fSetupFileXfer: TW_SETUPFILEXFER; // Not used yet
fSetupMemoryXfer: TW_SETUPMEMXFER; // Not used yet
fMemory: TW_MEMORY; // Not used yet
function fLoadTwain: Boolean;
procedure fUnloadTwain;
function fNativeXfer: Boolean;
function fMemoryXfer: Boolean; // Not used yet
function fFileXfer: Boolean; // Not used yet
function fGetDestination: TTransferType;
procedure fSetDestination(dest: TTransferType);
function Condition2String(ConditionCode: TW_UINT16): string;
procedure RaiseLastDataSourceManagerCondition(module: string);
procedure RaiseLastDataSourceCondition(module: string);
procedure TwainCheckDataSourceManager(res: TW_UINT16;
module: string);
procedure TwainCheckDataSource(res: TW_UINT16;
module: string);
function CallDataSourceManager(pOrigin: pTW_IDENTITY;
DG: TW_UINT32;
DAT: TW_UINT16;
MSG: TW_UINT16;
pData: TW_MEMREF): TW_UINT16;
function CallDataSource(DG: TW_UINT32;
DAT: TW_UINT16;
MSG: TW_UINT16;
pData: TW_MEMREF): TW_UINT16;
procedure XferMech;
procedure fSetProductname(pn: string);
function fGetProductname: string;
procedure fSetManufacturer(mf: string);
function fGetManufacturer: string;
procedure fSetProductFamily(pf: string);
function fGetProductFamily: string;
procedure fSetLanguage(lg: TLanguageType);
function fGetLanguage: TLanguageType;
procedure fSetCountry(ct: TCountryType);
function fGetCountry: TCountryType;
procedure SaveDefaultSourceEntry;
procedure RestoreDefaultSourceEntry;
procedure fSetCursor(cr: TCursor);
function fGetCursor: TCursor;
procedure fSetImageType(it: TImageType);
function fGetImageType: TImageType;
procedure fSetFilename(fn: string);
function fGetFilename: string;
procedure fSetVersionInfo(vi: string);
function fGetVersionInfo: string;
procedure fSetVersionMajor(vmaj: WORD);
procedure fSetVersionMinor(vmin: WORD);
function fGetVersionMajor: WORD;
function fGetVersionMinor: WORD;
protected
procedure ScanReady; dynamic; // Notifies when image transfer is
// ready
procedure fNewOnMessageHandler(var Msg: TMsg;
var Handled: Boolean); virtual;
public
// Public declarations
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Acquire(aBmp: TBitmap);
procedure OpenDataSource;
procedure CloseDataSource;
procedure InitTWAIN;
procedure OpenDataSourceManager;
procedure CloseDataSourceManager;
function IsDataSourceManagerOpen: Boolean;
procedure EnableDataSource;
// Procedure TWEnableDSUIOnly(ShowUI : Boolean);
procedure DisableDataSource;
function IsDataSourceOpen: Boolean;
function IsDataSourceEnabled: Boolean;
procedure SelectDataSource;
function IsTwainDriverAvailable: Boolean;
function ProcessSourceMessage(var Msg: TMsg): Boolean;
published
// Published declarations
// Properties, methods
property Destination: TTransferType
read fGetDestination write fSetDestination;
property TwainDriverFound: Boolean
read IsTwainDriverAvailable;
property Productname: string
read fGetProductname write fSetProductname;
property Manufacturer: string
read fGetManufacturer write fSetManufacturer;
property ProductFamily: string
read fGetProductFamily write fSetProductFamily;
property Language: TLanguageType
read fGetLanguage write fSetLanguage;
property Country: TCountryType
read fGetCountry write fSetCountry;
property ShowUI: Boolean
read fShowUI write fShowUI;
property Cursor: TCursor
read fGetCursor write fSetCursor;
property FileFormat: TImageType
read fGetImageType write fSetImageType;
property Filename: string
read fGetFilename write fSetFilename;
property VersionInfo: string
read fGetVersionInfo write fSetVersionInfo;
property VersionMajor: WORD
read fGetVersionMajor write fSetVersionMajor;
property VersionMinor: WORD
read fGetVersionMinor write fSetVersionMinor;
// Events
property OnScanReady: TNotifyEvent
read fScanReady write fScanReady;
end;
procedure Register;
type
DSMENTRYPROC = function(pOrigin: pTW_IDENTITY;
pDest: pTW_IDENTITY;
DG: TW_UINT32;
DAT: TW_UINT16;
MSG: TW_UINT16;
pData: TW_MEMREF): TW_UINT16; stdcall;
TDSMEntryProc = DSMENTRYPROC;
type
DSENTRYPROC = function(pOrigin: pTW_IDENTITY;
DG: TW_UINT32;
DAT: TW_UINT16;
MSG: TW_UINT16;
pData: TW_MEMREF): TW_UINT16; stdcall;
TDSEntryProc = DSENTRYPROC;
var
DS_Entry: TDSEntryProc = nil; // Initialize
DSM_Entry: TDSMEntryProc = nil; // Initialize
implementation
//---------------------------------------------------------------------
constructor TTWAIN.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// Initialize variables
appID.Version.Info := 'Twain component';
appID.Version.Country := TWCY_USA;
appID.Version.Language := TWLG_USA;
appID.Productname := 'SimpelSoft TWAIN module'; // This is the one that you are
// going to see in the UI
appID.ManuFacturer := 'SimpelSoft';
appID.ProductFamily := 'SimpelSoft components';
appID.Version.MajorNum := 1;
appID.Version.MinorNum := 0;
// appID.ID := Application.Handle;
fSetFilename('C:\TWAIN.BMP');
// fSetupFileXfer.FileName := 'C:\TWAIN.TMP':
fSetImageType(ffBMP);
// fSetupFileXfer.Format := TWFF_BMP;
// fSetupFileXfer.VRefNum := xx; // For Mac
// fSetupMemoryXfer.MinBufSize := xx;
// fSetupMemoryXfer.MaxBufSize := yy;
// fSetupMemoryXfer.Preferred := zz;
fMemory.Flags := TWFF_BMP;
// fMemory.Length := SizeOf(Mem);
// fMemory.TheMem := @Mem;
// fhWnd := Application.Handle;
fShowUI := True;
HDSMDLL := 0;
sDefaultSource := '';
fXfer := xfNative;
bDataSourceManagerOpen := False;
bDataSourceOpen := False;
bDataSourceEnabled := False;
end;
//---------------------------------------------------------------------
destructor TTWAIN.Destroy;
begin
if bDataSourceEnabled then
DisableDataSource;
if bDataSourceOpen then
CloseDataSource;
if bDataSourceManagerOpen then
CloseDataSourceManager;
fUnLoadTwain; // Loose the TWAIN_32.DLL
if sDefaultSource <> '' then
RestoreDefaultSourceEntry; // Write old entry back in WIN.INI
Application.OnMessage := fOldOnMessageHandler; // Restore old OnMessage
// handler
inherited Destroy;
end;
//---------------------------------------------------------------------
function TTWAIN.fGetVersionMajor: WORD;
begin
Result := appID.Version.MajorNum;
end;
//---------------------------------------------------------------------
function TTWAIN.fGetVersionMinor: WORD;
begin
Result := appID.Version.MinorNum;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetVersionMajor(vmaj: WORD);
begin
appID.Version.MajorNum := vmaj;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetVersionMinor(vmin: WORD);
begin
appID.Version.MinorNum := vmin;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetVersionInfo(vi: string);
var
I, L: Integer;
begin
FillChar(appID.Version.Info, SizeOf(appID.Version.Info), #0);
L := Length(vi);
if L = 0 then
Exit;
if L > 32 then
L := 32;
for I := 1 to L do
appID.Version.Info[I - 1] := vi[I];
end;
//---------------------------------------------------------------------
function TTWAIN.fGetVersionInfo: string;
var
I: Integer;
begin
Result := '';
I := 0;
if appID.Version.Info[I] <> #0 then
repeat
Result := Result + appID.Version.Info[I];
Inc(I);
until appID.Version.Info[I] = #0;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetImageType(it: TImageType);
begin
fSetupFileXfer.Format := TWFF_BMP; // Initialize
fMemory.Flags := TWFF_BMP; // Initialize
case it of
ffTIFF:
begin
fSetupFileXfer.Format := TWFF_TIFF;
fMemory.Flags := TWFF_TIFF;
end;
ffPICT:
begin
fSetupFileXfer.Format := TWFF_PICT;
fMemory.Flags := TWFF_PICT;
end;
ffBMP:
begin
fSetupFileXfer.Format := TWFF_BMP;
fMemory.Flags := TWFF_BMP;
end;
ffXBM:
begin
fSetupFileXfer.Format := TWFF_XBM;
fMemory.Flags := TWFF_XBM;
end;
ffJFIF:
begin
fSetupFileXfer.Format := TWFF_JFIF;
fMemory.Flags := TWFF_JFIF;
end;
ffFPX:
begin
fSetupFileXfer.Format := TWFF_FPX;
fMemory.Flags := TWFF_FPX;
end;
ffTIFFMULTI:
begin
fSetupFileXfer.Format := TWFF_TIFFMULTI;
fMemory.Flags := TWFF_TIFFMULTI;
end;
ffPNG:
begin
fSetupFileXfer.Format := TWFF_PNG;
fMemory.Flags := TWFF_PNG;
end;
ffSPIFF:
begin
fSetupFileXfer.Format := TWFF_SPIFF;
fMemory.Flags := TWFF_SPIFF;
end;
ffEXIF:
begin
fSetupFileXfer.Format := TWFF_EXIF;
fMemory.Flags := TWFF_EXIF;
end;
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetFilename(fn: string);
var
L, I: Integer;
begin
FillChar(fSetupFileXfer.FileName, SizeOf(fSetupFileXfer.Filename), #0);
L := Length(fn);
if L > 0 then
for I := 1 to L do
fSetupFileXfer.Filename[I - 1] := fn[I];
end;
//---------------------------------------------------------------------
function TTWAIN.fGetFilename: string;
var
I: Integer;
begin
Result := '';
I := 0;
if fSetupFileXfer.Filename[I] <> #0 then
repeat
Result := Result + fSetupFileXfer.Filename[I];
Inc(I);
until fSetupFileXfer.Filename[I] = #0;
end;
//---------------------------------------------------------------------
function TTWAIN.fGetImageType: TImageType;
begin
Result := ffUNKNOWN; // Initialize
case fSetupFileXfer.Format of
TWFF_TIFF: Result := ffTIFF;
TWFF_PICT: Result := ffPICT;
TWFF_BMP: Result := ffBMP;
TWFF_XBM: Result := ffXBM;
TWFF_JFIF: Result := ffJFIF;
TWFF_FPX: Result := ffFPX;
TWFF_TIFFMULTI: Result := ffTIFFMULTI;
TWFF_PNG: Result := ffPNG;
TWFF_SPIFF: Result := ffSPIFF;
TWFF_EXIF: Result := ffEXIF;
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetCursor(cr: TCursor);
begin
Screen.Cursor := cr;
end;
//---------------------------------------------------------------------
function TTWAIN.fGetCursor: TCursor;
begin
Result := Screen.Cursor;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetCountry(ct: TCountryType);
begin
case ct of
ctDenmark: appID.Version.Country := TWCY_DENMARK;
ctNetherlands: appID.Version.Country := TWCY_NETHERLANDS;
ctEngland: appID.Version.Country := TWCY_BRITAIN;
ctFinland: appID.Version.Country := TWCY_FINLAND;
ctFrance: appID.Version.Country := TWCY_FRANCE;
ctGermany: appID.Version.Country := TWCY_GERMANY;
ctItaly: appID.Version.Country := TWCY_ITALY;
ctNorWay: appID.Version.Country := TWCY_NORWAY;
ctSpain: appID.Version.Country := TWCY_SPAIN;
ctUSA: appID.Version.Country := TWCY_USA;
ctRussia: appID.Version.Country := TWCY_RUSSIA;
ctPortugal: appID.Version.Country := TWCY_PORTUGAL;
ctSweden: appID.Version.Country := TWCY_SWEDEN;
ctPoland: appID.Version.Country := TWCY_POLAND;
ctGreece: appID.Version.Country := TWCY_GREECE;
ctTurkey: appID.Version.Country := TWCY_TURKEY;
end;
end;
//---------------------------------------------------------------------
function TTWAIN.fGetCountry: TCountryType;
begin
Result := ctNetherlands; // Initialize
case appID.Version.Country of
TWCY_NETHERLANDS: Result := ctNetherlands;
TWCY_DENMARK: Result := ctDenmark;
TWCY_BRITAIN: Result := ctEngland;
TWCY_FINLAND: Result := ctFinland;
TWCY_FRANCE: Result := ctFrance;
TWCY_GERMANY: Result := ctGermany;
TWCY_NORWAY: Result := ctNorway;
TWCY_ITALY: Result := ctItaly;
TWCY_SPAIN: Result := ctSpain;
TWCY_USA: Result := ctUSA;
TWCY_RUSSIA: Result := ctRussia;
TWCY_PORTUGAL: Result := ctPortugal;
TWCY_SWEDEN: Result := ctSweden;
TWCY_TURKEY: Result := ctTurkey;
TWCY_GREECE: Result := ctGreece;
TWCY_POLAND: Result := ctPoland;
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetLanguage(lg: TLanguageType);
begin
case lg of
lgDanish: appID.Version.Language := TWLG_DAN;
lgDutch: appID.Version.Language := TWLG_DUT;
lgEnglish: appID.Version.Language := TWLG_ENG;
lgFinnish: appID.Version.Language := TWLG_FIN;
lgFrench: appID.Version.Language := TWLG_FRN;
lgGerman: appID.Version.Language := TWLG_GER;
lgNorwegian: appID.Version.Language := TWLG_NOR;
lgItalian: appID.Version.Language := TWLG_ITN;
lgSpanish: appID.Version.Language := TWLG_SPA;
lgAmerican: appID.Version.Language := TWLG_USA;
lgRussian: appID.Version.Language := TWLG_RUSSIAN;
lgPortuguese: appID.Version.Language := TWLG_POR;
lgSwedish: appID.Version.Language := TWLG_SWE;
lgPolish: appID.Version.Language := TWLG_POLISH;
lgGreek: appID.Version.Language := TWLG_GREEK;
lgTurkish: appID.Version.Language := TWLG_TURKISH;
end;
end;
//---------------------------------------------------------------------
function TTWAIN.fGetLanguage: TLanguageType;
begin
Result := lgDutch; // Initialize
case appID.Version.Language of
TWLG_DAN: Result := lgDanish;
TWLG_DUT: Result := lgDutch;
TWLG_ENG: Result := lgEnglish;
TWLG_FIN: Result := lgFinnish;
TWLG_FRN: Result := lgFrench;
TWLG_GER: Result := lgGerman;
TWLG_ITN: Result := lgItalian;
TWLG_NOR: Result := lgNorwegian;
TWLG_SPA: Result := lgSpanish;
TWLG_USA: Result := lgAmerican;
TWLG_RUSSIAN: Result := lgRussian;
TWLG_POR: Result := lgPortuguese;
TWLG_SWE: Result := lgSwedish;
TWLG_POLISH: Result := lgPolish;
TWLG_GREEK: Result := lgGreek;
TWLG_TURKISH: Result := lgTurkish;
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetManufacturer(mf: string);
var
I, L: Integer;
begin
FillChar(appID.Manufacturer, SizeOf(appID.Manufacturer), #0);
L := Length(mf);
if L = 0 then
Exit;
if L > 32 then
L := 32;
for I := 1 to L do
appID.Manufacturer[I - 1] := mf[I];
end;
//---------------------------------------------------------------------
function TTWAIN.fGetManufacturer: string;
var
I: Integer;
begin
Result := '';
I := 0;
if appID.Manufacturer[I] <> #0 then
repeat
Result := Result + appID.Manufacturer[I];
Inc(I);
until appID.Manufacturer[I] = #0;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetProductname(pn: string);
var
I, L: Integer;
begin
FillChar(appID.Productname, SizeOf(appID.Productname), #0);
L := Length(pn);
if L = 0 then
Exit;
if L > 32 then
L := 32;
for I := 1 to L do
appID.Productname[I - 1] := pn[I];
end;
//---------------------------------------------------------------------
function TTWAIN.fGetProductName: string;
var
I: Integer;
begin
Result := '';
I := 0;
if appID.ProductName[I] <> #0 then
repeat
Result := Result + appID.ProductName[I];
Inc(I);
until appID.ProductName[I] = #0;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetProductFamily(pf: string);
var
I, L: Integer;
begin
FillChar(appID.ProductFamily, SizeOf(appID.ProductFamily), #0);
L := Length(pf);
if L = 0 then
Exit;
if L > 32 then
L := 32;
for I := 1 to L do
appID.ProductFamily[I - 1] := pf[I];
end;
//---------------------------------------------------------------------
function TTWAIN.fGetProductFamily: string;
var
I: Integer;
begin
Result := '';
I := 0;
if appID.ProductFamily[I] <> #0 then
repeat
Result := Result + appID.ProductFamily[I];
Inc(I);
until appID.ProductFamily[I] = #0;
end;
//---------------------------------------------------------------------
procedure TTWAIN.ScanReady;
begin
if Assigned(fScanReady) then
fScanReady(Self);
end;
//---------------------------------------------------------------------
procedure TTWAIN.fSetDestination(dest: TTransferType);
begin
fXfer := dest;
end;
//---------------------------------------------------------------------
function TTWAIN.fGetDestination: TTransferType;
begin
Result := fXfer;
end;
//----------------------------------------------------------------------
function UpCaseStr(const s: string): string;
var
I, L: Integer;
begin
Result := s;
L := Length(Result);
if L > 0 then
begin
for I := 1 to L do
Result[I] := UpCase(Result[I]);
end;
// Result := s; // Minor bug, changed 23/05/03
end;
//----------------------------------------------------------------------
// Internal routine
//----------------------------------------------------------------------
function GetWinDir: string;
var
WD: array[0..MAX_PATH] of Char;
L: WORD;
begin
WD := #0;
GetWindowsDirectory(WD, MAX_PATH);
Result := StrPas(WD);
L := Length(Result);
// Remove the "\" if any
if L > 0 then
if Result[L] = '\' then
Result := Copy(Result, 1, L - 1);
end;
//----------------------------------------------------------------------
// Internal routine
//----------------------------------------------------------------------
procedure FileFindSubDir(const ffsPath: string;
var ffsBo: Boolean);
var
sr: TSearchRec;
begin
if FindFirst(ffsPath + '\*.*', faAnyFile, sr) = 0 then
repeat
if sr.Name <> '.' then
if sr.Name <> '..' then
if sr.Attr and faDirectory = faDirectory then
begin
FileFindSubDir(ffsPath + '\' + sr.name, ffsBo);
end
else
begin
if UpCaseStr(ExtractFileExt(sr.Name)) = '.DS' then
if UpCaseStr(sr.Name) <> 'WIATWAIN.DS' then
ffsBo := True;
end;
until FindNext(sr) <> 0;
// Error if SysUtils is not added in front of FindClose!
SysUtils.FindClose(sr);
end;
//----------------------------------------------------------------------
function TTWAIN.IsTwainDriverAvailable: Boolean;
var
sr: TSearchRec;
s: string;
Bo: Boolean;
begin
// This routine might not be failsafe!
// Under circumstances the twain drivers found in the directory
// %WINDOWS%\TWAIN_32\*.ds and below could be not properly installed!
Bo := False;
s := GetWinDir + '\TWAIN_32';
FileFindSubDir(s, Bo);
Result := Bo;
end;
//---------------------------------------------------------------------
procedure TTWAIN.SaveDefaultSourceEntry;
var
WinIni: TIniFile;
begin
if sDefaultSource <> '' then
Exit;
WinIni := TIniFile.Create(Ini_File_Name);
sDefaultSource := WinIni.ReadString('TWAIN', 'DEFAULT SOURCE', '');
WinIni.Free;
end;
//---------------------------------------------------------------------
procedure TTWAIN.RestoreDefaultSourceEntry;
var
WinIni: TIniFile;
begin
if sDefaultSource = '' then
Exit; // It is not changed by this component or it is not there...
WinIni := TIniFile.Create(Ini_File_Name);
WinIni.WriteString('TWAIN', 'DEFAULT SOURCE', sDefaultSource);
WinIni.Free;
sDefaultSource := '';
end;
//---------------------------------------------------------------------
procedure TTWAIN.InitTWAIN;
begin
appID.ID := Application.Handle;
fHwnd := Application.Handle;
fLoadTwain; // Load TWAIN_32.DLL
fOldOnMessageHandler := Application.OnMessage; // Save old pointer
Application.OnMessage := fNewOnMessageHandler; // Set to our handler
OpenDataSourceManager; // Open DS
end;
//---------------------------------------------------------------------
function TTWAIN.fLoadTwain: Boolean;
begin
if HDSMDLL = 0 then
begin
HDSMDLL := LoadLibrary(TWAIN_DLL_Name);
DSM_Entry := GetProcAddress(HDSMDLL, DSM_Entry_Name);
// if @DSM_Entry = nil then
// raise ETwainError.Create(SErrDSMEntryNotFound);
end;
Result := (HDSMDLL <> 0);
end;
//---------------------------------------------------------------------
procedure TTWAIN.fUnloadTwain;
begin
if HDSMDLL <> 0 then
begin
DSM_Entry := nil;
FreeLibrary(HDSMDLL);
HDSMDLL := 0;
end;
end;
//---------------------------------------------------------------------
function TTWAIN.Condition2String(ConditionCode: TW_UINT16): string;
begin
// Texts copied from PDF Documentation: Rework needed
case ConditionCode of
TWCC_BADCAP: Result :=
'Capability not supported by source or operation (get,' + CrLf +
'set) is not supported on capability, or capability had' + CrLf +
'dependencies on other capabilities and cannot be' + CrLf +
'operated upon at this time';
TWCC_BADDEST: Result := 'Unknown destination in DSM_Entry.';
TWCC_BADPROTOCOL: Result := 'Unrecognized operation triplet.';
TWCC_BADVALUE: Result :=
'Data parameter out of supported range.';
TWCC_BUMMER: Result :=
'General failure. Unload Source immediately.';
TWCC_CAPUNSUPPORTED: Result := 'Capability not supported by ' +
'Data Source.';
TWCC_CAPBADOPERATION: Result := 'Operation not supported on ' +
'capability.';
TWCC_CAPSEQERROR: Result :=
'Capability has dependencies on other capabilities and ' + CrLf +
'cannot be operated upon at this time.';
TWCC_DENIED: Result :=
'File System operation is denied (file is protected).';
TWCC_PAPERDOUBLEFEED,
TWCC_PAPERJAM: Result :=
'Transfer failed because of a feeder error';
TWCC_FILEEXISTS: Result :=
'Operation failed because file already exists.';
TWCC_FILENOTFOUND: Result := 'File not found.';
TWCC_LOWMEMORY: Result :=
'Not enough memory to complete the operation.';
TWCC_MAXCONNECTIONS: Result :=
'Data Source is connected to maximum supported number of ' +
CrLf + 'applications.';
TWCC_NODS: Result :=
'Data Source Manager was unable to find the specified Data ' +
'Source.';
TWCC_NOTEMPTY: Result :=
'Operation failed because directory is not empty.';
TWCC_OPERATIONERROR: Result :=
'Data Source or Data Source Manager reported an error to the' +
CrLf + 'user and handled the error. No application action ' +
'required.';
TWCC_SEQERROR: Result :=
'Illegal operation for current Data Source Manager' + CrLf +
'and Data Source state.';
TWCC_SUCCESS: Result := 'Operation was succesful.';
else
Result := Format('Unknown condition %.04x', [ConditionCode]);
end;
end;
///////////////////////////////////////////////////////////////////////
// RaiseLastDSMCondition (idea: like RaiseLastWin32Error) //
// Tries to get the status from the DSM and raises an exception //
// with it. //
///////////////////////////////////////////////////////////////////////
procedure TTWAIN.RaiseLastDataSourceManagerCondition(module: string);
var
status: TW_STATUS;
begin
Assert(@DSM_Entry <> nil);
if DSM_Entry(@appId, nil, DG_CONTROL, DAT_STATUS, MSG_GET, @status) <>
TWRC_SUCCESS then
raise ETwainError.Create(ERR_STATUS)
else
raise ETwainError.CreateFmt(ERR_DSM, [module,
Condition2String(status.ConditionCode)]);
end;
///////////////////////////////////////////////////////////////////////
// RaiseLastDSCondition //
// same again, but for the actual DS //
// (should be a method of DS) //
///////////////////////////////////////////////////////////////////////
procedure TTWAIN.RaiseLastDataSourceCondition(module: string);
var
status: TW_STATUS;
begin
Assert(@DSM_Entry <> nil);
if DSM_Entry(@appId, @dsID, DG_CONTROL, DAT_STATUS, MSG_GET, @status) <>
TWRC_SUCCESS then
raise ETwainError.Create(ERR_STATUS)
else
raise ETwainError.CreateFmt(ERR_DSM, [module,
Condition2String(status.ConditionCode)]);
end;
///////////////////////////////////////////////////////////////////////
// TwainCheckDSM (idea: like Win32Check or GDICheck in Graphics.pas) //
///////////////////////////////////////////////////////////////////////
procedure TTWAIN.TwainCheckDataSourceManager(res: TW_UINT16;
module: string);
begin
if res <> TWRC_SUCCESS then
begin
if res = TWRC_FAILURE then
RaiseLastDataSourceManagerCondition(module)
else
raise ETwainError.CreateFmt(ERR_UNKNOWN, [module, res]);
end;
end;
///////////////////////////////////////////////////////////////////////
// TwainCheckDS //
// same again, but for the actual DS //
// (should be a method of DS) //
///////////////////////////////////////////////////////////////////////
procedure TTWAIN.TwainCheckDataSource(res: TW_UINT16;
module: string);
begin
if res <> TWRC_SUCCESS then
begin
if res = TWRC_FAILURE then
RaiseLastDataSourceCondition(module)
else
raise ETwainError.CreateFmt(ERR_UNKNOWN, [module, res]);
end;
end;
///////////////////////////////////////////////////////////////////////
// CallDSMEntry: //
// Short form for DSM Calls: appId is not needed as parameter //
///////////////////////////////////////////////////////////////////////
function TTWAIN.CallDataSourceManager(pOrigin: pTW_IDENTITY;
DG: TW_UINT32;
DAT: TW_UINT16;
MSG: TW_UINT16;
pData: TW_MEMREF): TW_UINT16;
begin
Assert(@DSM_Entry <> nil);
Result := DSM_Entry(@appID,
pOrigin,
DG,
DAT,
MSG,
pData);
if (Result <> TWRC_SUCCESS) and (DAT <> DAT_EVENT) then
begin
end;
end;
///////////////////////////////////////////////////////////////////////
// Short form for (actual) DS Calls. appId and dsID are not needed //
// (this should be a DS class method) //
///////////////////////////////////////////////////////////////////////
function TTWAIN.CallDataSource(DG: TW_UINT32;
DAT: TW_UINT16;
MSG: TW_UINT16;
pData: TW_MEMREF): TW_UINT16;
begin
Assert(@DSM_Entry <> nil);
Result := DSM_Entry(@appID,
@dsID,
DG,
DAT,
MSG,
pData);
end;
///////////////////////////////////////////////////////////////////////
// A lot of the following code is a conversion from the //
// twain example program (and some comments are copied, too) //
// (The error handling is done differently) //
// Most functions should be moved to a DSM or DS class //
///////////////////////////////////////////////////////////////////////
procedure TTWAIN.OpenDataSourceManager;
begin
if not bDataSourceManagerOpen then
begin
Assert(appID.ID <> 0);
if not fLoadTwain then
raise ETwainError.Create(ERR_TWAIN_NOT_LOADED);
// appID.Id := fhWnd;
// appID.Version.MajorNum := 1;
// appID.Version.MinorNum := 0;
// appID.Version.Language := TWLG_USA;
// appID.Version.Country := TWCY_USA;
// appID.Version.Info := 'Twain Component';
appID.ProtocolMajor := 1; // TWON_PROTOCOLMAJOR;
appID.ProtocolMinor := 7; // TWON_PROTOCOLMINOR;
appID.SupportedGroups := DG_IMAGE or DG_CONTROL;
// appID.Productname := 'HP ScanJet 5p';
// appId.ProductFamily := 'ScanJet';
// appId.Manufacturer := 'Hewlett-Packard';
TwainCheckDataSourceManager(CallDataSourceManager(nil,
DG_CONTROL,
DAT_PARENT,
MSG_OPENDSM,
@fhWnd),
'OpenDataSourceManager');
bDataSourceManagerOpen := True;
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.CloseDataSourceManager;
begin
if bDataSourceOpen then
raise ETwainError.Create(ERR_DSM_OPEN);
if bDataSourceManagerOpen then
begin
// This call performs one important function:
// - tells the SM which application, appID.id, is requesting SM to
// close
// - be sure to test return code, failure indicates SM did not
// close !!
TwainCheckDataSourceManager(CallDataSourceManager(nil,
DG_CONTROL,
DAT_PARENT,
MSG_CLOSEDSM,
@fhWnd),
'CloseDataSourceManager');
bDataSourceManagerOpen := False;
end;
fUnLoadTwain; // Loose the DLL
if sDefaultSource <> '' then
RestoreDefaultSourceEntry;
end;
//---------------------------------------------------------------------
function TTWAIN.IsDataSourceManagerOpen: Boolean;
begin
Result := bDataSourceManagerOpen;
end;
//---------------------------------------------------------------------
procedure TTWAIN.OpenDataSource;
begin
Assert(bDataSourceManagerOpen, 'Data Source Manager must be open');
if not bDataSourceOpen then
begin
TwainCheckDataSourceManager(CallDataSourceManager(nil,
DG_CONTROL,
DAT_IDENTITY,
MSG_OPENDS,
@dsID),
'OpenDataSource');
bDataSourceOpen := True;
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.CloseDataSource;
begin
Assert(bDataSourceManagerOpen, 'Data Source Manager must be open');
if bDataSourceOpen then
begin
TwainCheckDataSourceManager(CallDataSourceManager(nil,
DG_CONTROL,
DAT_IDENTITY,
MSG_CLOSEDS,
@dsID),
'CloseDataSource');
bDataSourceOpen := False;
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.EnableDataSource;
var
twUI: TW_USERINTERFACE;
begin
Assert(bDataSourceOpen, 'Data Source must be open');
if not bDataSourceEnabled then
begin
FillChar(twUI, SizeOf(twUI), #0);
twUI.hParent := fhWnd;
twUI.ShowUI := fShowUI;
twUI.ModalUI := True;
TwainCheckDataSourceManager(CallDataSourceManager(@dsID,
DG_CONTROL,
DAT_USERINTERFACE,
MSG_ENABLEDS,
@twUI),
'EnableDataSource');
bDataSourceEnabled := True;
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.DisableDataSource;
var
twUI: TW_USERINTERFACE;
begin
Assert(bDataSourceOpen, 'Data Source must be open');
if bDataSourceEnabled then
begin
twUI.hParent := fhWnd;
twUI.ShowUI := TW_BOOL(TWON_DONTCARE8); (*!!!!*)
TwainCheckDataSourceManager(CallDataSourceManager(@dsID,
DG_CONTROL,
DAT_USERINTERFACE,
MSG_DISABLEDS,
@twUI),
'DisableDataSource');
bDataSourceEnabled := False;
end;
end;
//---------------------------------------------------------------------
function TTWAIN.IsDataSourceOpen: Boolean;
begin
Result := bDataSourceOpen;
end;
//---------------------------------------------------------------------
function TTWAIN.IsDataSourceEnabled: Boolean;
begin
Result := bDataSourceEnabled;
end;
//---------------------------------------------------------------------
procedure TTWAIN.SelectDataSource;
var
NewDSIdentity: TW_IDENTITY;
twRC: TW_UINT16;
begin
SaveDefaultSourceEntry;
Assert(not bDataSourceOpen, 'Data Source must be closed');
TwainCheckDataSourceManager(CallDataSourceManager(nil,
DG_CONTROL,
DAT_IDENTITY,
MSG_GETDEFAULT,
@NewDSIdentity),
'SelectDataSource1');
twRC := CallDataSourceManager(nil,
DG_CONTROL,
DAT_IDENTITY,
MSG_USERSELECT,
@NewDSIdentity);
case twRC of
TWRC_SUCCESS: dsID := NewDSIdentity; // log in new Source
TWRC_CANCEL: ; // keep the current Source
else
TwainCheckDataSourceManager(twRC, 'SelectDataSource2');
end;
end;
(*******************************************************************
Functions from CAPTEST.C
*******************************************************************)
procedure TTWAIN.XferMech;
var
cap: TW_CAPABILITY;
pVal: pTW_ONEVALUE;
begin
fXfer := xfNative; // Override
cap.Cap := ICAP_XFERMECH;
cap.ConType := TWON_ONEVALUE;
cap.hContainer := GlobalAlloc(GHND, SizeOf(TW_ONEVALUE));
Assert(cap.hContainer <> 0);
try
pval := pTW_ONEVALUE(GlobalLock(cap.hContainer));
Assert(pval <> nil);
try
pval.ItemType := TWTY_UINT16;
case fXfer of
xfMemory: pval.Item := TWSX_MEMORY;
xfFile: pval.Item := TWSX_FILE;
xfNative: pval.Item := TWSX_NATIVE;
end;
finally
GlobalUnlock(cap.hContainer);
end;
TwainCheckDataSource(CallDataSource(DG_CONTROL,
DAT_CAPABILITY,
MSG_SET,
@cap),
'XferMech');
finally
GlobalFree(cap.hContainer);
end;
end;
///////////////////////////////////////////////////////////////////////
function TTWAIN.ProcessSourceMessage(var Msg: TMsg): Boolean;
var
twRC: TW_UINT16;
event: TW_EVENT;
pending: TW_PENDINGXFERS;
begin
Result := False;
if bDataSourceManagerOpen and bDataSourceOpen then
begin
event.pEvent := @Msg;
event.TWMessage := 0;
twRC := CallDataSource(DG_CONTROL,
DAT_EVENT,
MSG_PROCESSEVENT,
@event);
case event.TWMessage of
MSG_XFERREADY:
begin
case fXfer of
xfNative: fNativeXfer;
xfMemory: fMemoryXfer;
xfFile: fFileXfer;
end;
TwainCheckDataSource(CallDataSource(DG_CONTROL,
DAT_PENDINGXFERS,
MSG_ENDXFER,
@pending),
'Check for Pending Transfers');
if pending.Count > 0 then
TwainCheckDataSource(CallDataSource(
DG_CONTROL,
DAT_PENDINGXFERS,
MSG_RESET,
@pending),
'Abort Pending Transfers');
DisableDataSource;
CloseDataSource;
ScanReady; // Event
end;
MSG_CLOSEDSOK,
MSG_CLOSEDSREQ:
begin
DisableDataSource;
CloseDataSource;
ScanReady // Event
end;
end;
Result := not (twRC = TWRC_NOTDSEVENT);
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.Acquire(aBmp: TBitmap);
begin
// fOldOnMessageHandler := Application.OnMessage; // Save old pointer
// Application.OnMessage := fNewOnMessageHandler; // Set to our handler
// OpenDataSourceManager; // Open DS
fBitmap := aBmp;
OpenDataSourceManager;
OpenDataSource;
XferMech; // Must be written for xfMemory and xfFile
EnableDataSource;
end;
//---------------------------------------------------------------------
// Must be written!
function TTWAIN.fMemoryXfer: Boolean;
var
twRC: TW_UINT16;
begin
Result := False;
twRC := CallDataSource(DG_IMAGE,
DAT_IMAGEMEMXFER,
MSG_GET,
nil);
case twRC of
TWRC_XFERDONE: Result := True;
TWRC_CANCEL: ;
TWRC_FAILURE: ;
end;
end;
//---------------------------------------------------------------------
// Must be written!
function TTWAIN.fFileXfer: Boolean;
var
twRC: TW_UINT16;
begin
// Not yet implemented!
Result := False;
twRC := CallDataSource(DG_IMAGE,
DAT_IMAGEFILEXFER,
MSG_GET,
nil);
case twRC of
TWRC_XFERDONE: Result := True;
TWRC_CANCEL: ;
TWRC_FAILURE: ;
end;
end;
//---------------------------------------------------------------------
function TTWAIN.fNativeXfer: Boolean;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function DibNumColors(dib: Pointer): Integer;
var
lpbi: PBITMAPINFOHEADER;
lpbc: PBITMAPCOREHEADER;
bits: Integer;
begin
lpbi := dib;
lpbc := dib;
if lpbi.biSize <> SizeOf(BITMAPCOREHEADER) then
begin
if lpbi.biClrUsed <> 0 then
begin
Result := lpbi.biClrUsed;
Exit;
end;
bits := lpbi.biBitCount;
end
else
bits := lpbc.bcBitCount;
case bits of
1: Result := 2;
4: Result := 16; // 4?
8: Result := 256; // 8?
else
Result := 0;
end;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var
twRC: TW_UINT16;
hDIB: TW_UINT32;
hBmp: HBITMAP;
lpDib: ^TBITMAPINFO;
lpBits: PChar;
ColorTableSize: Integer;
dc: HDC;
begin
Result := False;
twRC := CallDataSource(DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, @hDIB);
case twRC of
TWRC_XFERDONE:
begin
lpDib := GlobalLock(hDIB);
try
ColorTableSize := (DibNumColors(lpDib) *
SizeOf(RGBQUAD));
lpBits := PChar(lpDib);
Inc(lpBits, lpDib.bmiHeader.biSize);
Inc(lpBits, ColorTableSize);
dc := GetDC(0);
try
hBMP := CreateDIBitmap(dc, lpdib.bmiHeader,
CBM_INIT, lpBits, lpDib^, DIB_RGB_COLORS);
fBitmap.Handle := hBMP;
Result := True;
finally
ReleaseDC(0, dc);
end;
finally
GlobalUnlock(hDIB);
GlobalFree(hDIB);
end;
end;
TWRC_CANCEL: ;
TWRC_FAILURE: RaiseLastDataSourceManagerCondition('Native Transfer');
end;
end;
//---------------------------------------------------------------------
procedure TTWAIN.fNewOnMessageHandler(var Msg: TMsg;
var Handled: Boolean);
begin
Handled := ProcessSourceMessage(Msg);
if Assigned(fOldOnMessageHandler) then
fOldOnMessageHandler(Msg, Handled)
end;
Взято с
Delphi Knowledge BaseКак работать со всеми фреймами, отображёнными в данный момент в WebBrowser?
Как работать со всеми фреймами, отображёнными в данный момент в WebBrowser?
Взято из FAQ:
Перевод материала с сайта members.home.com/hfournier/webbrowser.htm
Данный пример показывает как определить в каких фреймах разрешена команда 'copy':
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
for i := 0 to (WebBrowser1.OleObject.Document.frames.Length - 1) do
if WebBrowser1.OleObject.Document.frames.item(i).document.queryCommandEnabled('Copy') then
ShowMessage('copy command is enabled for frame no.' + IntToStr(i));
end;
Автор: Peter Friese
Как работать со всеми ячейками < TABLE> ?
Как работать со всеми ячейками < TABLE> ?
Взято из FAQ:
Перевод материала с сайта members.home.com/hfournier/webbrowser.htm
Пример показывает как добавить содержимое каждой ячейки в TMemo:
procedure TForm1.Button1Click(Sender: TObject);
var
i, j: integer;
ovTable: OleVariant;
begin
// Я использовал первую таблицу на странице в ка?естве примера
ovTable := WebBrowser1.OleObject.Document.all.tags('TABLE').item(0); for i := 0 to (ovTable.Rows.Length - 1) do
begin
for j := 0 to (ovTable.Rows.Item(i).Cells.Length - 1) do
begin
Memo1.Lines.Add(ovTable.Rows.Item(i).Cells.Item(j).InnerText;
end;
end;
end;
Как распечатать bitmap?
Как распечатать bitmap?
procedureStretchPrint(R: TRect; ABitmap: Graphics.TBitmap);
var
dc: HDC;
isDcPalDevice: Bool;
hDibHeader: THandle;
pDibHeader: pointer;
hBits: THandle;
pBits: pointer;
ppal: PLOGPALETTE;
pal: hPalette;
Oldpal: hPalette;
i: integer;
begin
pal := 0;
OldPal := 0;
{Get the screen dc}
dc := GetDc(0);
{Allocate memory for a DIB structure}
hDibHeader := GlobalAlloc(GHND, sizeof(TBITMAPINFO) + (sizeof(TRGBQUAD) * 256));
{get a pointer to the alloced memory}
pDibHeader := GlobalLock(hDibHeader);
{fill in the dib structure with info on the way we want the DIB}
FillChar(pDibHeader^, sizeof(TBITMAPINFO) + (sizeof(TRGBQUAD) * 256), #0);
PBITMAPINFOHEADER(pDibHeader)^.biSize := sizeof(TBITMAPINFOHEADER);
PBITMAPINFOHEADER(pDibHeader)^.biPlanes := 1;
PBITMAPINFOHEADER(pDibHeader)^.biBitCount := 8;
PBITMAPINFOHEADER(pDibHeader)^.biWidth := ABitmap.width;
PBITMAPINFOHEADER(pDibHeader)^.biHeight := ABitmap.height;
PBITMAPINFOHEADER(pDibHeader)^.biCompression := BI_RGB;
{find out how much memory for the bits}
GetDIBits(dc, ABitmap.Handle, 0, ABitmap.height, nil, TBitmapInfo(pDibHeader^),
DIB_RGB_COLORS);
{Alloc memory for the bits}
hBits := GlobalAlloc(GHND, PBitmapInfoHeader(pDibHeader)^.BiSizeImage);
{Get a pointer to the bits}
pBits := GlobalLock(hBits);
{Call fn again, but this time give us the bits!}
GetDIBits(dc, ABitmap.Handle, 0, ABitmap.height, pBits, PBitmapInfo(pDibHeader)^,
DIB_RGB_COLORS);
{Release the screen dc}
ReleaseDc(0, dc);
{Just incase the printer drver is a palette device}
isDcPalDevice := false;
if GetDeviceCaps(Printer.Canvas.Handle, RASTERCAPS) and RC_PALETTE = RC_PALETTE then
begin
{Create palette from dib}
GetMem(pPal, sizeof(TLOGPALETTE) + (255 * sizeof(TPALETTEENTRY)));
FillChar(pPal^, sizeof(TLOGPALETTE) + (255 * sizeof(TPALETTEENTRY)), #0);
pPal^.palVersion := $300;
pPal^.palNumEntries := 256;
for i := 0 to (pPal^.PalNumEntries - 1) do
begin
pPal^.palPalEntry[i].peRed := PBitmapInfo(pDibHeader)^.bmiColors[i].rgbRed;
pPal^.palPalEntry[i].peGreen := PBitmapInfo(pDibHeader)^.bmiColors[i].rgbGreen;
pPal^.palPalEntry[i].peBlue := PBitmapInfo(pDibHeader)^.bmiColors[i].rgbBlue;
end;
pal := CreatePalette(pPal^);
FreeMem(pPal, sizeof(TLOGPALETTE) + (255 * sizeof(TPALETTEENTRY)));
oldPal := SelectPalette(Printer.Canvas.Handle, Pal, false);
isDcPalDevice := true
end;
{send the bits to the printer}
StretchDiBits(Printer.Canvas.Handle, R.Left, R.Top, R.Right - R.Left,
R.Bottom - R.Top, 0, 0, ABitmap.Width, ABitmap.Height, pBits,
PBitmapInfo(pDibHeader)^, DIB_RGB_COLORS, SRCCOPY);
{Just incase you printer drver is a palette device}
if isDcPalDevice = true then
begin
SelectPalette(Printer.Canvas.Handle, oldPal, false);
DeleteObject(Pal);
end;
{Clean up allocated memory}
GlobalUnlock(hBits);
GlobalFree(hBits);
GlobalUnlock(hDibHeader);
GlobalFree(hDibHeader);
end;
Взято с
Delphi Knowledge BaseКак распечатать Excel файл?
Как распечатать Excel файл?
{
This is a simple example how to print an Excel file using OLE.
}
uses
ComObj;
procedure TForm1.Button1Click(Sender: TObject);
var
ExcelApp: OLEVariant;
begin
// Create an Excel instance
// Excel Instanz erzeugen
ExcelApp := CreateOleObject('Excel.Application');
try
ExcelApp.Workbooks.Open('C:\test\xyz.xls');
// you can also modify some settings from PageSetup
// Man kann auch noch einige Einstellungen von "Seite Einrichten" anpassen
ExcelApp.ActiveSheet.PageSetup.Orientation := xlLandscape;
// Print it out
// Ausdrucken
ExcelApp.Worksheets.PrintOut;
finally
// Close Excel
// Excel wieder schliessen
if not VarIsEmpty(ExcelApp) then
begin
ExcelApp.Quit;
ExcelApp := Unassigned;
end;
end;
end;
Взято с сайта
Как распечатать PRN file?
Как распечатать PRN file?
uses
Printers, Winspool;
function SpoolFile(const FileName, PrinterName: string): Integer;
var
Buffer: record
JobInfo: record // ADDJOB_INFO_1
Path: PChar;
JobID: DWORD;
end;
PathBuffer: array[0..255] of Char;
end;
SizeNeeded: DWORD;
Handle: THandle;
PrtName: string;
ok: Boolean;
begin
// Flush job to printer
PrtName := PrinterName;
if PrtName = '' then
PrtName := Printer.Printers[Printer.PrinterIndex]; // Default printer name
ok := False;
if OpenPrinter(PChar(PrtName), Handle, nil) then
if AddJob(Handle, 1, @Buffer, SizeOf(Buffer), SizeNeeded) then
if CopyFile(PChar(FileName), Buffer.JobInfo.Path, True) then
if ScheduleJob(Handle, Buffer.JobInfo.JobID) then
ok := True;
if not ok then Result := GetLastError
else
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if SpoolFile('c:\test.prn', Printer.Printers[0]) = 0 then
ShowMessage('No error...');
end;
Взято с сайта
Как распечатать TImage?
Как распечатать TImage?
uses
Printers;
procedure TForm1.Button1Click(Sender: TObject);
var
ScaleX, ScaleY: Integer;
RR: TRect;
begin
with Printer do
begin
BeginDoc;
// Mit BeginDoc wird ein Druckauftrag initiiert.
// The StartDoc function starts a print job.
try
ScaleX := GetDeviceCaps(Handle, logPixelsX) div PixelsPerInch;
ScaleY := GetDeviceCaps(Handle, logPixelsY) div PixelsPerInch;
// Informationen uber die Auflosung
// Retrieves information about the Pixels per Inch of the Printer.
RR := Rect(0, 0, Image1.picture.Width * scaleX, Image1.Picture.Height * ScaleY);
Canvas.StretchDraw(RR, Image1.Picture.Graphic);
// An die Auflosung anpassen
// Stretch to fit
finally
EndDoc; //Methode EndDoc beendet den aktuellen Druckauftrag und schlie?t die
// Textdatei-Variable.
// Steht in finally - um auch bei Abbruch des Druckauftrages Papierausgabe
// sicherzustellen
end;
end;
end;
// Based on posting to borland.public.delphi.winapi by Rodney E Geraghty, 8/8/97.
procedure PrintBitmap(Canvas: TCanvas; DestRect: TRect; Bitmap: TBitmap);
var
BitmapHeader: pBitmapInfo;
BitmapImage: Pointer;
HeaderSize: DWORD;
ImageSize: DWORD;
begin
GetDIBSizes(Bitmap.Handle, HeaderSize, ImageSize);
GetMem(BitmapHeader, HeaderSize);
GetMem(BitmapImage, ImageSize);
try
GetDIB(Bitmap.Handle, Bitmap.Palette, BitmapHeader^, BitmapImage^);
StretchDIBits(Canvas.Handle,
DestRect.Left, DestRect.Top, // Destination Origin
DestRect.Right - DestRect.Left, // Destination Width
DestRect.Bottom - DestRect.Top, // Destination Height
0, 0, // Source Origin
Bitmap.Width, Bitmap.Height, // Source Width & Height
BitmapImage,
TBitmapInfo(BitmapHeader^),
DIB_RGB_COLORS,
SRCCOPY)
finally
FreeMem(BitmapHeader);
FreeMem(BitmapImage)
end
end {PrintBitmap};
// from www.experts-exchange.com
uses
printers;
procedure DrawImage(Canvas: TCanvas; DestRect: TRect; ABitmap: TBitmap);
var
Header, Bits: Pointer;
HeaderSize: DWORD;
BitsSize: DWORD;
begin
GetDIBSizes(ABitmap.Handle, HeaderSize, BitsSize);
Header := AllocMem(HeaderSize);
Bits := AllocMem(BitsSize);
try
GetDIB(ABitmap.Handle, ABitmap.Palette, Header^, Bits^);
StretchDIBits(Canvas.Handle, DestRect.Left, DestRect.Top,
DestRect.Right, DestRect.Bottom,
0, 0, ABitmap.Width, ABitmap.Height, Bits, TBitmapInfo(Header^),
DIB_RGB_COLORS, SRCCOPY);
finally
FreeMem(Header, HeaderSize);
FreeMem(Bits, BitsSize);
end;
end;
procedure PrintImage(Image: TImage; ZoomPercent: Integer);
// if ZoomPercent=100, Image will be printed across the whole page
var
relHeight, relWidth: integer;
begin
Screen.Cursor := crHourglass;
Printer.BeginDoc;
with Image.Picture.Bitmap do
begin
if ((Width / Height) > (Printer.PageWidth / Printer.PageHeight)) then
begin
// Stretch Bitmap to width of PrinterPage
relWidth := Printer.PageWidth;
relHeight := MulDiv(Height, Printer.PageWidth, Width);
end
else
begin
// Stretch Bitmap to height of PrinterPage
relWidth := MulDiv(Width, Printer.PageHeight, Height);
relHeight := Printer.PageHeight;
end;
relWidth := Round(relWidth * ZoomPercent / 100);
relHeight := Round(relHeight * ZoomPercent / 100);
DrawImage(Printer.Canvas, Rect(0, 0, relWidth, relHeight), Image.Picture.Bitmap);
end;
Printer.EndDoc;
Screen.cursor := crDefault;
end;
// Example Call:
procedure TForm1.Button1Click(Sender: TObject);
begin
// Print image at 40% zoom:
PrintImage(Image1, 40);
end;
Взято с сайта
Как распечатать TStringGrid?
Как распечатать TStringGrid?
uses
Printers;
procedure PrintGrid(sGrid: TStringGrid; sTitle: string);
var
X1, X2: Integer;
Y1, Y2: Integer;
TmpI: Integer;
F: Integer;
TR: TRect;
begin
Printer.Title := sTitle;
Printer.BeginDoc;
Printer.Canvas.Pen.Color := 0;
Printer.Canvas.Font.Name := 'Times New Roman';
Printer.Canvas.Font.Size := 12;
Printer.Canvas.Font.Style := [fsBold, fsUnderline];
Printer.Canvas.TextOut(0, 100, Printer.Title);
for F := 1 to sGrid.ColCount - 1 do
begin
X1 := 0;
for TmpI := 1 to (F - 1) do
X1 := X1 + 5 * (sGrid.ColWidths[TmpI]);
Y1 := 300;
X2 := 0;
for TmpI := 1 to F do
X2 := X2 + 5 * (sGrid.ColWidths[TmpI]);
Y2 := 450;
TR := Rect(X1, Y1, X2 - 30, Y2);
Printer.Canvas.Font.Style := [fsBold];
Printer.Canvas.Font.Size := 7;
Printer.Canvas.TextRect(TR, X1 + 50, 350, sGrid.Cells[F, 0]);
Printer.Canvas.Font.Style := [];
for TmpI := 1 to sGrid.RowCount - 1 do
begin
Y1 := 150 * TmpI + 300;
Y2 := 150 * (TmpI + 1) + 300;
TR := Rect(X1, Y1, X2 - 30, Y2);
Printer.Canvas.TextRect(TR, X1 + 50, Y1 + 50, sGrid.Cells[F, TmpI]);
end;
end;
Printer.EndDoc;
end;
//Examplem, Beispiel:
procedure TForm1.Button1Click(Sender: TObject);
begin
PrintGrid(StringGrid1, 'Print Stringgrid');
end;
Взято с сайта
Как распечатать WEB страничку при помощи HTML контрола?
Как распечатать WEB страничку при помощи HTML контрола?
Можно использовать два метода HTML контрола: AutoPrint или PrintPage.
Пример использования AutoPrint:
--------------------------------------------------------------------------------
Как распечатать WEB страничку при помощи HTML контрола
Можно использовать два метода HTML контрола: AutoPrint или PrintPage.
Пример использования AutoPrint:
uses Printers;
procedure TForm1.Button1Click(Sender: TObject);
var
OldCur: TCursor;
begin
OldCur := Screen.Cursor;
with Printer do begin
BeginDoc;
HTML1.AutoPrint(handle);
Title := HTML1.URL;
EndDoc;
end;
Screen.Cursor := OldCur;
end;
Взято с Исходников.ru
Как расшарить диск?
Как расшарить диск?
Автор: Repairman
Это модуль для Share любого диска или папки как на локальном, так и на удаленном компьютере (если, конечно у Вас права администратора и на компе разрешено удаленное администрирование, для локальной машины это не обязательно... ;-))
Следует отметить, что под NT некоторые процедуры находятся в других DLL...
Функция SetShareOnDisk - ставит шару, RemoveShareFromDisk - снимает ее.
unit Share;
//(c)2002 <Repairman> repairman@uzel.ru
interface
type
TPassw = string[8];
TNetName = string[12];
function SetShareOnDisk(HostName: string; //имя компьютера
LocalPath: string; //папка которую надо открыть для доступа
NetName: TNetName; //имя расшаренной папки в сети
Remark: string; //комментарий, видимый в сети
Access: word; //доступ
RO_Passw: TPassw; //пароль на чтение
RW_Passw: TPassw //пароль на полный доступ
): boolean;
function RemoveShareFromDisk(HostName: string; //имя компьютера
NetName: string; //сетевое имя папки которую надо закрыть
LocalPath: string //локальный путь папки
): boolean;
var
ShareResult: word;
//-------------------------------------------------------------------------------------------
implementation
uses SysUtils, Windows, ShlObj;
function NetShareAdd(ServerName: PChar; //указатель на имя компьютера, например '\\Server'#0, если свой, то можно nil
Level: Word; //уровень структуры Share_info, здесь 50
PShareInfo: PChar; //указатель на структуру Share_Info
ParmErr: DWord) //указатель на ???
: dword; stdcall; external 'svrapi.dll'; //svrapi для Win9X, NetApi32 для NT
function NetShareDel(ServerName: PChar;
NetName: PChar;
Reserved: DWord): dword; stdcall; external 'svrapi.dll';
type
_share_info_50 = record //структура Share уровня 50
NetName: array[1..13] of char; //Как будет называться диск в сети
SType: byte; //тип =0 (STYPE_DISKTREE) - шарить диски
Flags: word; //флаги $0191,$0192,$0193....(доступ из сети)
Remark: PChar; //указатель на комментарий, видимый из сети
Path: PChar; //указатель на имя ресурса, например 'c:\'#0
RW_Password: array[1..9] of char; //пароль для полного доступа, если не нужен =#0
RO_Password: array[1..9] of char; //пароль для доступа на чтение, если не нужен =#0
end;
//----------------------------
function SetShareOnDisk(HostName, LocalPath: string; NetName: TNetName; Remark: string;
Access: word; RO_Passw, RW_Passw: TPassw): boolean;
var ShareInfo: _Share_Info_50;
begin
Result := false;
StrPCopy(@ShareInfo.NetName, NetName);
ShareInfo.SType := 0;
ShareInfo.Flags := Access;
ShareInfo.Remark := PChar(Remark);
ShareInfo.Path := PChar(LocalPath);
StrPCopy(@ShareInfo.RO_Password, RO_Passw);
StrPCopy(@ShareInfo.RW_Password, RW_Passw);
ShareResult := NetShareAdd(PChar(HostName), 50, @ShareInfo, $0000002A); //вызываем Share
if ShareResult <> 0 then Exit; //расшарить неудалось
SHChangeNotify(SHCNE_NETSHARE, SHCNF_PATH, PChar(LocalPath), nil); //сказать шеллу об изменениях
Result := true;
end;
//----------------------------
function RemoveShareFromDisk(HostName, NetName, LocalPath: string): boolean;
begin
Result := false;
ShareResult := NetShareDel(PChar(HostName), PChar(NetName), 0); //удалить шару
if ShareResult <> 0 then Exit;
SHChangeNotify(SHCNE_NETUNSHARE, SHCNF_PATH, PChar(LocalPath), nil); //сказать шеллу об изменениях
Result := true;
end;
//----------------------------
end.
Взято с Исходников.ru
Как разбить "цвет" на составляющие и наоборот?
Как разбить "цвет" на составляющие и наоборот?
GetRValue
GetBValue
GetGValue
В обратную сторону RGB()
Автор Vit
Взято с Vingrad.ru
Как разделить обработку OnClick
Как разделить обработку OnClick и OnDblClick? Ведь OnClick будет вызываться всегда, и перед DblClick.
Именно так и происходит в Windows - посылаются оба сообщения. Для того чтобы обработать только какое-то одно событие необходимо чуть "задержать" выполнение OnClick. Сделать это можно следующим способом:
procedure TForm1.ListBox1Click(Sender: TObject);
var
Msg: TMsg;
TargetTime: Longint;
begin
{ get the maximum time to wait for a double-click message }
TargetTime := GetTickCount + GetDoubleClickTime;
{ cycle until DblClick received or wait time run out }
while GetTickCount < TargetTime do
if PeekMessage(Msg, ListBox1.Handle, WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK, WM_NOREMOVE)
then Exit; { Double click }
MessageDlg('Single clicked', mtInformation, [mbOK], 0);
end;
Как разделить строку на элементы, Аналог VB функции Split
Как разделить строку на элементы, Аналог VB функции Split
Вариант 1.
В Дельфи есть специальный класс для хранения массивов строк - TStringList - очень рекомендую. Вот как вашу строку превратить в TStringList:
Объявление переменной
var t:TStringList;
begin
t:=TStringList.create; //создаём класс
t.text:=stringReplace('Ваша строка для разделения',' ',#13#10,[rfReplaceAll]);//мы заменяем все пробелы на символы конца строки
//теперь можно убедится что у вас строка разбина на элементы:
showmessage(t[0]);
showmessage(t[1]);
showmessage(t[2]);
showmessage(t[3]);
...
//после работы надо уничтожить класс
t.free;
Автор Vit
Взято с Vingrad.ru
Вариант 2. Используем стандартные массивы:
var a:array of string;//наш массив
s:string;//строка которую мы будем разбивать
begin
s:='Windows Messages SysUtils Variants Classes Graphics Controls Forms';
Repeat //мы постепенно заполняем массив на каждом шаге цикла по 1 элементу
setlength(a,length(a)+1);//увеличиваем размер массива на 1
if pos(' ',s)>0 then //если есть пробел то надо взять слово до пробела
begin
a[length(a)-1]:=copy(s,1, pos(' ',s));//присвоение последнему элементу массива первого слова
s:=copy(s,pos(' ',s)+1, length(s));//удаляем из строки первое слово
end
else//в строке осталось только одно слово
begin
a[length(a)-1]:=s;// присвоим последнее слово
break;//выход из цикла
end;
Until False;//цикл бесконечный, выход изнутри
//теперь проверяем что получили
showmessage(a[0]);
showmessage(a[1]);
showmessage(a[2]);
После использования массива не забудте освободить память a:=nil или setlength(a,0)
Автор Vit
Взято с Vingrad.ru
procedure SplitOnWords(const s:string; Delimiters:set of char; Strings:TStrings);
var
p,sp:PChar;
str:string;
begin
include(Delimiters,#0); //чтоб уж наверняк
p:=pointer(s);
while true do
begin
//пропускаем все разделители в начале
while p^ in Delimiters do
if p^=#0 then
exit
else
inc(p);
sp:=p;
//пока не кончилось слово.
while not (p^ in Delimiters) do inc(p);
//запоминаем слово
SetLength(str,cardinal(p)-cardinal(sp));
Move(sp^,pointer(str)^,cardinal(p)-cardinal(sp));
Strings.Add(str);
end;
end;
Автор Fantasist
Взято с Vingrad.ru
См. также
Как различаются между собой Paint-события: Invalidate, Update и Refresh?
Как различаются между собой Paint-события: Invalidate, Update и Refresh?
Invalidate весь объект перерисовывается заново; обычно перерисовывается только часть бывшая перед этим закрытой
Update незамедлительная перерисовка
Refresh Invalidate + Update
Как разместить прозрачную надпись на TBitmap?
Как разместить прозрачную надпись на TBitmap?
var
OldBkMode : integer;
begin
Image1.Picture.Bitmap.Canvas.Font.Color := clBlue;
OldBkMode := SetBkMode(Image1.Picture.Bitmap.Canvas.Handle,TRANSPARENT);
Image1.Picture.Bitmap.Canvas.TextOut(10, 10, 'Hello');
SetBkMode(Image1.Picture.Bitmap.Canvas.Handle,OldBkMode);
end;
Взято из
DELPHI VCL FAQ
Перевод с английского Подборку, перевод и адаптацию материала подготовил Aziz(JINX)
специально для
Как разрешить / запретить переключение между задачами?
Как разрешить / запретить переключение между задачами?
(только для ALT+TAB и CTRL+ESC)
Это не совсем профессиональный способ, но он работает! Мы просто эмулируем запуск и остановку скринсейвера.
Procedure TaskSwitchingStatus( State : Boolean );
Var
OldSysParam : LongInt;
Begin
SystemParametersInfo( SPI_SCREENSAVERRUNNING, Word( State ), @OldSysParam, 0 );
End;
Взято с Исходников.ru
Как разрезать wav файл?
Как разрезать wav файл?
type
TWaveHeader = record
ident1: array[0..3] of Char; // Must be "RIFF"
len: DWORD; // remaining length after this header
ident2: array[0..3] of Char; // Must be "WAVE"
ident3: array[0..3] of Char; // Must be "fmt "
reserv: DWORD; // Reserved Size
wFormatTag: Word; // format type
nChannels: Word; // number of channels (i.e. mono, stereo, etc.)
nSamplesPerSec: DWORD; //sample rate
nAvgBytesPerSec: DWORD; //for buffer estimation
nBlockAlign: Word; //block size of data
wBitsPerSample: Word; //number of bits per sample of mono data
cbSize: Word; //the count in bytes of the size of
ident4: array[0..3] of Char; //Must be "data"
end;
You can load the file header with this function:
function GetWaveHeader(FileName: TFilename): TWaveHeader;
const
riff = 'RIFF';
wave = 'WAVE';
var
f: TFileStream;
w: TWaveHeader;
begin
if not FileExists(Filename) then
exit;
try
f := TFileStream.create(Filename, fmOpenRead);
f.Read(w, Sizeof(w));
if w.ident1 <> riff then
begin
Showmessage('This is not a RIFF File');
exit;
end;
if w.ident2 <> wave then
begin
Showmessage('This is not a valid wave file');
exit;
end;
finally
f.free;
end;
Result := w;
end;
Now we have all for creating the code for spliting the wave file:
function SplitWave(Source, Dest1, Dest2: TFileName; Pos: Integer): Boolean;
var
f1, f2, f3: TfileStream;
w: TWaveHeader;
p: Integer;
begin
Result:=False
if not FileExists(Source) then
exit;
try
w := GetWaveHeader(Source);
p := Pos - Sizeof(TWaveHeader);
f1 := TFileStream.create(Source, fmOpenRead);
f2 := TFileStream.create(Dest1, fmCreate);
f3 := TFileStream.create(Dest2, fmCreate);
{++++++++++Create file 1 ++++++++++++++++}
w.len := p;
f2.Write(w, Sizeof(w));
f1.position := Sizeof(w);
f2.CopyFrom(f1, p);
{++++++++++++++++++++++++++++++++++++++++}
{+++++++++++Create file 2 +++++++++++++++}
w.len := f1.size - Pos;
f3.write(w, Sizeof(w));
f1.position := Pos;
f3.CopyFrom(f1, f1.size - pos);
{++++++++++++++++++++++++++++++++++++++++}
finally
f1.free;
f2.free;
f3.free;
end;
Result:=True;
end;
Взято с
Delphi Knowledge BaseКак реализовать обработку информации одновременно несколькими потоками
Как реализовать обработку информации одновременно несколькими потоками
Автор: Садыков Алексей Николаевич
Запускайте Delphi. Итак, наша программа будет представлять из себя форму с двумя edit'ами и кнопкой. Добавьте их на форму.
При нажатии на кнопку будут осуществляться некоторые долгие вычисления. Если бы мы не использовали потоки, то, пока эти вычисления не закончатся, делать мы ничего бы не смогли. Надо было бы ждать. Но, так как потоки у нас будут, то во время долгих вычислений можно будет что-нибудь вводить во второй edit (он, собственно, только для этого и существует). В первый же edit наш поток будет выводить некоторые промежуточные результаты своей работы.
Добавьте в программу еще один модуль (меню File, New, Unit).
Внесите в окно кода нового модуля следующий код:
unit Unit2;
interface
uses
Classes;
type
TMyThread = class(TThread) //Новый класс
private
answer: Integer;
protected
procedure ShowResult;
procedure Execute; override;
end;
implementation
uses
SysUtils, Unit1;
//Процедура для вывода информации из потока
procedure TMyThread.ShowResult;
begin
Form1.Edit1.Text := IntToStr(answer);
end;
//Длинная процедура
procedure TMyThread.Execute;
var
i: Integer;
begin
for i := 1 to 10000 do
begin
answer := answer + 1;
Synchronize(ShowResult);
end;
end;
end.
Немного комментария по коду. В нашем модуле мы вводим новый класс TMyThread как «потомок» TThread. В экземпляре нашего класса и будет выполнятся отдельный поток программы. В классе есть процедура ShowResult для вывода информации из работающего потока в основной поток (форму) нашей программы. Кроме того, в классе есть наша версия метода Execute из родительского класса TThread. Обратите внимание, что в нашей реализации Execute мы пишем
Synchronize(ShowResult);
Тем самым наш поток что-то отправляет в основной поток программы (в данном случае, значение переменной answer). Делаем мы это посредством вызова Synchronize, в котором в качестве параметра указываем имя нужной процедуры.
Теперь переходим к нашему основному модулю Unit1. Во-первых, добавьте в секцию uses ссылку на Unit2:
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Unit2;
Во-вторых, напишите обработчик для нажатия кнопки:
procedure TForm1.Button1Click(Sender: TObject);
var
MyThread: TMyThread;
begin
MyThread := TMyThread.Create(False);
end;
Тут мы создаем второй поток для нашего приложения. Параметр False означает, что метод Execute для нашего потока вызовется немедленно.
Запускайте программу. Нажимайте на кнопку. В первом edit'е замелькают промежуточные результаты работы второго потока. Во время его работы вы можете вводить информацию во второй edit ? т.е. работа одного потока не мешает работе другого.
Взято с
Как реализовать сверхточный таймер?
Как реализовать сверхточный таймер?
Windows is not a real time operating system so it is not really able to reliably achieve high accuracy timing without using a device driver. The best I have been able to get is a few nanoseconds using QueryPerformanceCounter. This is the procedure I use:
var
WaitCal: Int64;
procedure Wait(ns: Integer);
var
Counter, Freq, WaitUntil: Int64;
begin
if QueryPerformanceCounter(Counter) then
begin
QueryPerformanceFrequency(Freq);
WaitUntil := Counter + WaitCal + (ns * (Freq div 1000000));
while Counter < WaitUntil do
QueryPerformanceCounter(Counter);
end
else
Sleep(ns div 1000);
end;
To get improved accuracy do this a little while before using Wait()
var
Start, Finish: Int64;
Application.ProcessMessages;
Sleep(10);
QueryPerformanceCounter(Start);
Wait(0);
QueryPerformanceCounter(Finish);
WaitCal := Start - Finish;
A trick I have found to increase the reliability of this on my computer is to call Wait like this:
Application.ProcessMessages;
Sleep(0);
DoSomething;
Wait(10);
DoSomethingElse;
Взято из
Как редактировать таблицы виртуальных и динамических методов?
Как редактировать таблицы виртуальных и динамических методов?
unitEditorVMTandDMTTables;
interface
// функция служит для выяснения существования VMT у класса
// возвращает True, если класс имеет VMT и False - если нет
function IsVMTExist(Cls: TClass): Boolean;
// процедура служит для замены адреса метода в VMT класса со смещением
// Offset(должно быть кратно 4) новым адресом, хранящимся в NewMet
// примечание: перед вызовом этой процедуры проверяйте существование
// VMT у класса функцией IsVMTExist
procedure VirtMethodReplace(Cls: TClass; Offset: LongWord; NewMet: Pointer); overload;
// процедура служит для замены адреса метода, хранящегося в OldMet,
// в VMT класса новым адресом, хранящимся в NewMet
// примечание: перед вызовом этой процедуры проверяйте существование
// VMT у класса функцией IsVMTExist
procedure VirtMethodReplace(Cls: TClass; OldMet, NewMet: Pointer); overload;
// функция служит для замены адреса динамического метода класса с индексом,
// хранящимся в Index, новым адресом, хранящимся в NewMet
// возвращает True, если метод с данным индексом найден и False - если нет
function DynMethodReplace(Cls: TClass; Index: Word; NewMet: Pointer): Boolean; overload;
// функция служит для замены адреса динамического метода класса, хранящегося
// в OldMet, новым адресом, хранящимся в NewMet
// возвращает True, если метод с данным адресом найден и False - если нет
function DynMethodReplace(Cls: TClass; OldMet, NewMet: Pointer): Boolean; overload;
implementation
// функция служит для получения указателя на байт, следующий за адресом
// последнего метода в VMT класса
// возвращает nil в случае, если у класса нет VMT
// функция является "внутренней" в модуле
// (используется другими подпрограммами и не объявлена в секции interface)
// , поэтому используйте её только если
// Вы полностью уверены в своих действиях(она изменяет "рабочие" регистры
// ECX и EDX)
function GetVMTEnd(Cls: TClass): Pointer;
asm
// Вход: Cls --> EAX
// Выход: Result --> EAX
PUSH EBX
MOV ECX, 8
MOV EBX, -1
MOV EDX, vmtSelfPtr
@@cycle:
ADD EDX, 4
CMP [EAX + EDX], EAX
JE @@vmt_not_found
JB @@continue
CMP [EAX + EDX], EBX
JAE @@continue
MOV EBX, [EAX + EDX]
@@continue:
DEC ECX
JNZ @@cycle
MOV EAX, EBX
JMP @@exit
@@vmt_not_found:
XOR EAX, EAX
@@exit:
POP EBX
end;
function IsVMTExist(Cls: TClass): Boolean;
asm
// Вход: Cls --> EAX
// Выход: Result --> AL
CALL GetVMTEnd
TEST EAX, EAX
JZ @@vmt_not_found
MOV AL, 1
@@vmt_not_found:
end;
procedure VirtMethodReplace(Cls: TClass; Offset: LongWord; NewMet: Pointer); overload;
asm
// Вход: Cls --> EAX, Offset --> EDX, NewMet --> ECX
MOV [EAX + EDX], ECX
end;
procedure VirtMethodReplace(Cls: TClass; OldMet, NewMet: Pointer); overload;
asm
// Вход: Cls --> EAX, OldMet --> EDX, NewMet --> ECX
PUSH EDI
MOV EDI, EAX
PUSH ECX
PUSH EDX
PUSH EAX
CALL GetVMTEnd
POP EDX
SUB EAX, EDX
SHR EAX, 2
POP EDX
POP ECX
PUSH ECX
MOV ECX, EAX
MOV EAX, EDX
POP EDX
REPNE SCASD
JNE @@OldMet_not_found
MOV [EDI - 4], EDX
@@OldMet_not_found:
POP EDI
end;
function DynMethodReplace(Cls: TClass; Index: Word; NewMet: Pointer): Boolean; overload;
asm
// Вход: Cls --> EAX, Index --> DX, NewMet --> ECX
// Выход: Result --> AL
PUSH EDI
PUSH ESI
MOV ESI, ECX
XOR EAX, EDX
XOR EDX, EAX
XOR EAX, EDX
JMP @@start
@@cycle:
MOV EDX, [EDX]
@@start:
MOV EDI, [EDX].vmtDynamicTable
TEST EDI, EDI
JZ @@get_parent_dmt
MOVZX ECX, WORD PTR [EDI]
PUSH ECX
ADD EDI, 2
REPNE SCASW
JE @@Index_found
POP ECX
@@get_parent_dmt:
MOV EDX, [EDX].vmtParent
TEST EDX, EDX
JNZ @@cycle
JMP @@Index_not_found
@@Index_found:
POP EAX
SHL EAX, 1
SUB EAX, ECX
MOV [EDI + EAX * 2 - 4], ESI
MOV AL, 1
JMP @@exit
@@Index_not_found:
XOR AL, AL
@@exit:
POP ESI
POP EDI
end;
function DynMethodReplace(Cls: TClass; OldMet, NewMet: Pointer): Boolean; overload;
asm
// Вход: Cls --> EAX, OldMet --> EDX, NewMet --> ECX
// Выход: Result --> AL
PUSH EDI
PUSH ESI
MOV ESI, ECX
XOR EAX, EDX
XOR EDX, EAX
XOR EAX, EDX
JMP @@start
@@cycle:
MOV EDX, [EDX]
@@start:
MOV EDI, [EDX].vmtDynamicTable
TEST EDI, EDI
JZ @@get_parent_dmt
MOVZX ECX, WORD PTR [EDI]
LEA EDI, EDI + 2 * ECX + 2
REPNE SCASD
JE @@OldMet_found
@@get_parent_dmt:
MOV EDX, [EDX].vmtParent
TEST EDX, EDX
JNZ @@cycle
JMP @@OldMet_not_found
@@OldMet_found:
MOV [EDI - 4], ESI
MOV AL, 1
JMP @@exit
@@OldMet_not_found:
XOR AL, AL
@@exit:
POP ESI
POP EDI
end;
end.
Автор
___ALex___ Форум:Как результат Query сделать в виде постоянной таблицы?
Как результат Query сделать в виде постоянной таблицы?
Traditionally, to write the results of a query to disk, you use a TBatchMove and a TTable in addition to your query. But you can short-circuit this process by making a couple of simple, direct calls to the BDE.
Make sure you have BDE declared in your uses section
procedureMakePermTable(Qry: TQuery; PermTableName: string);
var
h: HDBICur;
ph: PHDBICur;
begin
Qry.Prepare;
Check(dbiQExec(Qry.StmtHandle, ph));
h := ph^;
Check(DbiMakePermanent(h, PChar(PermTableName), True));
end;
Взято с
Delphi Knowledge BaseКак рисовать картинки в пунктах меню?
Как рисовать картинки в пунктах меню?
unitDN_Win;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, Menus, StdCtrls,
type
TDNForm = class(TForm)
MainMenu1: TMainMenu;
cm_MainExit: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure cm_MainExitClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
BM:TBitmap;
Procedure WMDrawItem(var Msg:TWMDrawItem); message wm_DrawItem;
Procedure WMMeasureItem(var Msg:TWMMeasureItem); message
wm_MeasureItem;
end;
var
DNForm : TDNForm;
implementation
{$R *.DFM}
var
Comm,yMenu : word;
procedure TDNForm.FormCreate(Sender: TObject);
begin
yMenu:=GetSystemMetrics(SM_CYMENU);
comm:=cm_MainExit.Command;
ModifyMenu(MainMenu1.Handle,0,mf_ByPosition or mf_OwnerDraw,comm,'Go');
end;{TDNForm.FormCreate}
procedure TDNForm.cm_MainExitClick(Sender: TObject);
begin
DNForm.Close;
end;{TDNForm.cmExitClick}
Procedure TDNForm.WMMeasureItem(var Msg:TWMMeasureItem);
Begin
with Msg.MeasureItemStruct^ do
if ItemID=comm then begin ItemWidth:=yMenu; Itemheight:=yMenu; end;
End;{WMMeasureItem}
Procedure TDNForm.WMDrawItem(var Msg:TWMDrawItem);
var
MemDC:hDC;
BM:hBitMap;
mtd:longint;
Begin
with Msg.DrawItemStruct^ do
begin
if ItemID=comm then
begin
BM:=LoadBitMap(hInstance,'dver');
MemDC:=CreateCompatibleDC(hDC);{hDC ? TDrawItemStruct}
SelectObject(MemDC,BM); {rcItem ? TDrawItemStruct}
if ItemState=ods_Selected then mtd:=NotSrcCopy else mtd:=SrcCopy;
StretchBlt(hDC,rcItem.left,rcItem.top,yMenu,yMenu,MemDC,0,0,24,23,mtd);
DeleteDC(MemDC);
DeleteObject(BM);
end;
end{with}
End;{TDNForm.WMDrawItem}
end.
Eugeny Sverchkov
es906@kolnpp.elektra.ru
(2:5031/12.23)
Автор:
StayAtHomeВзято из
Как рисовать линии (или ещё что-нибудь) на экране (TDesktopCanvas)
Как рисовать линии (или ещё что-нибудь) на экране (TDesktopCanvas)
{
Пример рисует две горизонтальные линии на экране используя TDesktopCanvas.
}
program TrinitronTraining;
uses
Messages, Windows, Graphics, Forms;
type
TDesktopCanvas = class(TCanvas)
private
DC : hDC;
function GetWidth:Integer;
function GetHeight:Integer;
public
constructor Create;
destructor Destroy; override;
published
property Width: Integer read GetWidth;
property Height: Integer read GetHeight;
end;
{ Объект TDesktopCanvas }
function TDesktopCanvas.GetWidth:Integer;
begin
Result:=GetDeviceCaps(Handle,HORZRES);
end;
function TDesktopCanvas.GetHeight:Integer;
begin
Result:=GetDeviceCaps(Handle,VERTRES);
end;
constructor TDesktopCanvas.Create;
begin
inherited Create;
DC := GetDC(0);
Handle := DC;
end;
destructor TDesktopCanvas.Destroy;
begin
Handle := 0;
ReleaseDC(0, DC);
inherited Destroy;
end;
Const
YCount = 2;
Var
desktop : TDesktopCanvas;
dx,dy : Integer;
i : Integer;
F : Array[1..YCount] of TForm;
function CreateLine(Y : Integer) : TForm;
begin
Result := TForm.Create(Application);
with Result do begin
Left := 0;
Top := y;
Width := dx;
Height := 1;
BorderStyle := bsNone;
FormStyle := fsStayOnTop;
Visible := True;
end;
end;
procedure ProcessMessage;
var
Msg : TMsg;
begin
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
if Msg.Message = WM_QUIT then Application.Terminate;
end;
begin
desktop := TDesktopCanvas.Create;
try
dx := desktop.Width;
dy := desktop.Height div (YCount+1);
finally
desktop.free;
end;
for i:=1 to YCount do F[i]:=CreateLine(i*dy);
Application.NormalizeTopMosts;
ShowWindow(Application.Handle, SW_Hide);
for i:=1 to YCount do
SetWindowPos(F[i].Handle, HWND_TOPMOST, 0,0,0,0, SWP_NOACTIVATE+SWP_NOMOVE+SWP_NOSIZE);
{ следующие строки используются для того, чтобы не останавливаться
repeat
ProcessMessage;
until false;
{}
Sleep(15000);
for i:=1 to YCount do F[i].Free;
end.
Взято с Исходников.ru
Как рисовать на компоненте, если свойство Canvas недоступно?
Как рисовать на компоненте, если свойство Canvas недоступно?
У всех компонентов, порожденных от TCustomControl, имеется свойство Canvas типа TCanvas.
Если свойство Canvas недоступно, Вы можете достучаться до него созданием потомка и переносом этого свойства в раздел Public.
{ Example. We recommend You to create this component through Component Wizard.
In Delphi 1 it can be found as 'File|New Component...', and can be found
as 'Component|New Component...' in Delphi 2 or above. }
type
TcPanel = class(TPanel)
public
property Canvas;
end;
Akzhan Abdulin
(2:5040/55)
Если у объекта нет свойства Canvas (у TDBEdit, вpоде-бы нет), по кpайней меpе в D3 можно использовать класс TControlCanvas. Пpимеpное использование:
var cc: TControlCanvas;
...
cc := TControlCanvas.Create;
cc.Control := youControl;
...
и далее как обычно можно использовать методы Canvas.
Andrew Velikoredchanin
(2:5026/29.3)
Как рисовать в чужом окне или по всему экрану
Как рисовать в чужом окне или по всему экрану
procedure DrawOnScreen;
var
ScreenDC: hDC;
begin
ScreenDC := GetDC(0); {получить контекст экрана}
Ellipse(ScreenDC, 0, 0, 200, 200); {нарисовать}
ReleaseDC(0, ScreenDC); {освободить контекст}
end;
Взято с Исходников.ru
Как рисовать за пределами формы
Как рисовать за пределами формы
Создайте обработчик сообщения для WM_NCPAINT. Следующий пример рисует красную расмку вокруг формы шириной в один пиксель.
type
TForm1 = class(TForm)
private
{ Private declarations }
procedure WMNCPaint(var Msg : TWMNCPaint); message WM_NCPAINT;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.WMNCPaint(var Msg: TWMNCPaint);
var
dc : hDc;
Pen : hPen;
OldPen : hPen;
OldBrush : hBrush;
begin
inherited;
dc := GetWindowDC(Handle);
msg.Result := 1;
Pen := CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
OldPen := SelectObject(dc, Pen);
OldBrush := SelectObject(dc, GetStockObject(NULL_BRUSH));
Rectangle(dc, 0,0, Form1.Width, Form1.Height);
SelectObject(dc, OldBrush);
SelectObject(dc, OldPen);
DeleteObject(Pen);
ReleaseDC(Handle, Canvas.Handle);
end;
Взято с Исходников.ru
Как с помощью API поместить Label на Form?
Как с помощью API поместить Label на Form?
var
hLabel : HWND ;
...
hLabel := CreateWindow ( 'STATIC', 'test', WS_CHILD or WS_VISIBLE, 0, 0, 200, 40, hWnd, NULL, hInstance, NULL );
Автор ответа: Baa
Примечание: Vit
Скорее всего последний параметр не "NULL", а "Nil" (NULL в паскале - варианта для обозначения пустого поля в базе данных)
Взято с Vingrad.ru
program Project1;
uses
Windows,
Messages;
const
myClassName= 'myWindow';
var
handleWnd, Label1 : THandle;
WndClass: TWndClass;
Msg: TMsg;
function WindowProc(Window: HWnd; AMessage, WParam,
LParam: Longint): Longint; stdcall;
begin
WindowProc:= DefWindowProc(Window, AMessage, WParam, LParam);
case AMessage of
{WM_COMMAND: if lParam = Button1 then
MessageBox( 0, 'Вы нажали кнопку!', 'Информация',
MB_OK or MB_ICONINFORMATION); }
WM_DESTROY: Halt;
end;
end;
begin
with WndClass do
begin
hInstance := hInstance;
lpszClassName:= myClassName;
style := cs_hRedraw or cs_vRedraw;
hbrBackground:= color_btnface +1;
lpfnWndProc := @WindowProc;
hCursor := LoadCursor(0, idc_Arrow);
hIcon := LoadIcon(0, IDI_EXCLAMATION);
lpszMenuName := NIL;
cbWndExtra := 0;
cbClsExtra := 0;
end;
RegisterClass( WndClass );
handleWnd:= CreateWindow(myClassName, 'Hажми кнопку', ws_OverlappedWindow,
400, 300, 200, 100, 0, 0, hInstance , NIL);
if handleWnd = 0 then
begin
MessageBox( 0, 'Error', NIL, MB_OK );
Exit;
end;
Label1:= CreateWindow( 'Label', 'Text',
WS_VISIBLE or WS_CHILD or WM_SETTEXT,
20, 10, 60, 23, handleWnd, 0, hInstance, nil);
ShowWindow(handleWnd, SW_SHOW);
UpdateWindow(handleWnd);
while GetMessage(Msg, handleWnd, 0, 0) do
begin
TranslateMessage(Msg) ;
DispatchMessage(Msg) ;
end;
end.
Автор ответа: alex-co
Взято с Vingrad.ru
Как считать сигнал с микрофона?
Как считать сигнал с микрофона?
В Windows нет разделения каналов записи по источникам.
CD-ROM ----------|
| |--- Динамики
Микрофон --------| |
|-- Windows --|--- Записывающие программы
Линейный вход ---| |
| |--- Линейный выход
MIDI ------------|
Все поступающие в систему звуки смешиваются, и лишь после этого их получает программа.
Для получения звукового сигнала нужно воспользоваться WinAPI.
WaveInOpen открывает доступ к микрофону.
Одновременно только одна программа может работать с микрофоном.
Заодно Вы указываете, какая нужна частота, сколько бит на значение и размер буфера.
От последнего зависит, как часто и в каком объеме информация будет поступать в программу.
Далее нужно выделить память для буфера и вызвать функцию WaveInAddBuffer,
которая передаст Windows пустой буфер.
После вызова WaveInStart Windows начнет заполнять буфер,
и, после его заполнения, пошлет сообщение MM_WIM_DATA.
В нем нужно обработать полученную информацию и вновь вызвать WaveInAddBuffer,
тем самым указав, что буфер пуст.
Функции WaveInReset и WaveInClose прекратят поступление информации в программу и закроют доступ к микрофону.
Эта программа считывает сигнал с микрофона и выводит его на экран.
Частота сигнала - 22050 Гц. Количество бит определяется флажком, размер буфера TrackBar-ом.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls, MMSystem;
type
TData8 = array [0..127] of byte;
PData8 = ^TData8;
TData16 = array [0..127] of smallint;
PData16 = ^TData16;
TPointArr = array [0..127] of TPoint;
PPointArr = ^TPointArr;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
PaintBox1: TPaintBox;
TrackBar1: TTrackBar;
CheckBox1: TCheckBox;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
procedure OnWaveIn(var Msg: TMessage); message MM_WIM_DATA;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
var
WaveIn: hWaveIn;
hBuf: THandle;
BufHead: TWaveHdr;
bufsize: integer;
Bits16: boolean;
p: PPointArr;
stop: boolean = false;
procedure TForm1.Button1Click(Sender: TObject);
var
header: TWaveFormatEx;
BufLen: word;
buf: pointer;
begin
BufSize := TrackBar1.Position * 500 + 100; { Размер буфера }
Bits16 := CheckBox1.Checked;
with header do begin
wFormatTag := WAVE_FORMAT_PCM;
nChannels := 1; { количество каналов }
nSamplesPerSec := 22050; { частота }
wBitsPerSample := integer(Bits16) * 8 + 8; { 8 / 16 бит }
nBlockAlign := nChannels * (wBitsPerSample div 8);
nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
cbSize := 0;
end;
WaveInOpen(Addr(WaveIn), WAVE_MAPPER, addr(header),
Form1.Handle, 0, CALLBACK_WINDOW);
BufLen := header.nBlockAlign * BufSize;
hBuf := GlobalAlloc(GMEM_MOVEABLE and GMEM_SHARE, BufLen);
Buf := GlobalLock(hBuf);
with BufHead do begin
lpData := Buf;
dwBufferLength := BufLen;
dwFlags := WHDR_BEGINLOOP;
end;
WaveInPrepareHeader(WaveIn, Addr(BufHead), sizeof(BufHead));
WaveInAddBuffer(WaveIn, addr(BufHead), sizeof(BufHead));
GetMem(p, BufSize * sizeof(TPoint));
stop := true;
WaveInStart(WaveIn);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if stop = false then Exit;
stop := false;
while not stop do Application.ProcessMessages;
stop := false;
WaveInReset(WaveIn);
WaveInUnPrepareHeader(WaveIn, addr(BufHead), sizeof(BufHead));
WaveInClose(WaveIn);
GlobalUnlock(hBuf);
GlobalFree(hBuf);
FreeMem(p, BufSize * sizeof(TPoint));
end;
procedure TForm1.OnWaveIn;
var
i: integer;
data8: PData8;
data16: PData16;
h: integer;
XScale, YScale: single;
begin
h := PaintBox1.Height;
XScale := PaintBox1.Width / BufSize;
if Bits16 then begin
data16 := PData16(PWaveHdr(Msg.lParam)^.lpData);
YScale := h / (1 shl 16);
for i := 0 to BufSize - 1 do
p^[i] := Point(round(i * XScale),
round(h / 2 - data16^[i] * YScale));
end else begin
Data8 := PData8(PWaveHdr(Msg.lParam)^.lpData);
YScale := h / (1 shl 8);
for i := 0 to BufSize - 1 do
p^[i] := Point(round(i * XScale),
round(h - data8^[i] * YScale));
end;
with PaintBox1.Canvas do begin
Brush.Color := clWhite;
FillRect(ClipRect);
Polyline(Slice(p^, BufSize));
end;
if stop
then WaveInAddBuffer(WaveIn, PWaveHdr(Msg.lParam),
SizeOf(TWaveHdr))
else stop := true;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Button2.Click;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
if stop then begin
Button2.Click;
Button1.Click;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TrackBar1.OnChange := CheckBox1Click;
Button1.Caption := 'Start';
Button2.Caption := 'Stop';
CheckBox1.Caption := '16 / 8 bit';
end;
end.
Всего доброго,
Даниил Карапетян.
На сайте http://delphi4all.narod.ru Вы найдете более 100 советов по Delphi.
email: delphi4all@narod.ru
Как сделать 24bit dithering?
Как сделать 24bit dithering?
{... }
type
PIntegerArray = ^TIntegerArray;
TIntegerArray = array[0..maxInt div sizeof(integer) - 2] of integer;
TColor3 = packed record
b, g, r: byte;
end;
TColor3Array = array[0..maxInt div sizeof(TColor3) - 2] of TColor3;
PColor3Array = ^TColor3Array;
procedure Swap(var p1, p2: PIntegerArray);
var
t: PIntegerArray;
begin
t := p1;
p1 := p2;
p2 := t;
end;
function clamp(x, min, max: integer): integer;
begin
result := x;
if result < min then
result := min;
else
if result > max then
result := max;
end;
procedure Dither(bmpS, bmpD: TBitmap);
var
bmpS, bmpD: TBitmap;
scanlS, scanlD: PColor3Array;
error1R, error1G, error1B,
error2R, error2G, error2B: PIntegerArray;
x, y: integer;
dx: integer;
c, cD: TColor3;
sR, sG, sB: integer;
dR, dG, dB: integer;
eR, eG, eB: integer;
begin
bmpD.Width := bmpS.Width;
bmpD.Height := bmpS.Height;
bmpS.PixelFormat := pf24bit;
bmpD.PixelFormat := pf24bit;
error1R := AllocMem((bmpS.Width + 2) * sizeof(integer));
error1G := AllocMem((bmpS.Width + 2) * sizeof(integer));
error1B := AllocMem((bmpS.Width + 2) * sizeof(integer));
error2R := AllocMem((bmpS.Width + 2) * sizeof(integer));
error2G := AllocMem((bmpS.Width + 2) * sizeof(integer));
error2B := AllocMem((bmpS.Width + 2) * sizeof(integer));
{dx holds the delta for each iteration as we zigzag, it'll change between 1 and -1}
dx := 1;
for y := 0 to bmpS.Height - 1 do
begin
scanlS := bmpS.ScanLine[y];
scanlD := bmpD.ScanLine[y];
if dx > 0 then
x := 0
else
x := bmpS.Width - 1;
while (x >= 0) and (x < bmpS.Width) do
begin
c := scanlS[x];
sR := c.r;
sG := c.g;
sB := c.b;
eR := error1R[x + 1];
eG := error1G[x + 1];
eB := error1B[x + 1];
dR := (sR * 16 + eR) div 16;
dG := (sR * 16 + eR) div 16;
dB := (sR * 16 + eR) div 16;
{actual downsampling}
dR := clamp(dR, 0, 255) and (255 shl 4);
dG := clamp(dR, 0, 255) and (255 shl 4);
dB := clamp(dR, 0, 255) and (255 shl 4);
cD.r := dR;
cD.g := dG;
cD.b := dB;
scanlD[x] := cD;
eR := sR - dR;
eG := sG - dG;
eB := sB - dB;
inc(error1R[x + 1 + dx], (eR * 7)); {next}
inc(error1G[x + 1 + dx], (eG * 7));
inc(error1B[x + 1 + dx], (eB * 7));
inc(error2R[x + 1], (eR * 5)); {top}
inc(error2G[x + 1], (eG * 5));
inc(error2B[x + 1], (eB * 5));
inc(error2R[x + 1 + dx], (eR * 1)); {diag forward}
inc(error2G[x + 1 + dx], (eG * 1));
inc(error2B[x + 1 + dx], (eB * 1));
inc(error2R[x + 1 - dx], (eR * 3)); {diag backward}
inc(error2G[x + 1 - dx], (eG * 3));
inc(error2B[x + 1 - dx], (eB * 3));
inc(x, dx);
end;
dx := dx * -1;
Swap(error1R, error2R);
Swap(error1G, error2G);
Swap(error1B, error2B);
FillChar(error2R^, sizeof(integer) * (bmpS.Width + 2), 0);
FillChar(error2G^, sizeof(integer) * (bmpS.Width + 2), 0);
FillChar(error2B^, sizeof(integer) * (bmpS.Width + 2), 0);
end;
FreeMem(error1R);
FreeMem(error1G);
FreeMem(error1B);
FreeMem(error2R);
FreeMem(error2G);
FreeMem(error2B);
end;
Взято с
Delphi Knowledge BaseКак сделать ADO-connection?
Как сделать ADO-connection?
uses
ComObj;
function OpenConnection(ConnectionString: AnsiString): Integer;
var
ADODBConnection: OleVariant;
begin
ADODBConnection := CreateOleObject('ADODB.Connection');
ADODBConnection.CursorLocation := 3; // User client
ADODBConnection.ConnectionString := ConnectionString;
Result := 0;
try
ADODBConnection.Open;
except
Result := -1;
end;
end;
function DataBaseConnection_Test(bMessage: Boolean): AnsiString;
var
asTimeout, asUserName, asPassword, asDataSource, ConnectionString: AnsiString;
iReturn: Integer;
OldCursor: TCursor;
begin
OldCursor := Screen.Cursor;
Screen.Cursor := crHourGlass;
asTimeout := '150';
asUserName := 'NT_Server';
asPassword := 'SA';
asDataSource := 'SQL Server - My DataBase';
ConnectionString := 'Data Source = ' + asDataSource +
'User ID = ' + asUserName +
'Password = ' + asPassword +
'Mode = Read|Write;Connect Timeout = ' + asTimeout;
try
iReturn := OpenConnection(ConnectionString);
if (bMessage) then
begin
if (iReturn = 0) then
Application.MessageBox('Connection OK!', 'Information', MB_OK)
else if (iReturn = -1) then
Application.MessageBox('Connection Error!', 'Error', MB_ICONERROR + MB_OK);
end;
if (iReturn = 0) then
Result := ConnectionString
else if (iReturn = -1) then
Result := '';
finally
Screen.Cursor := OldCursor;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DataBaseConnection_Test(True);
end;
Взято с сайта
Как сделать анимацию минимизации формы?
Как сделать анимацию минимизации формы?
In FormShow:
var
RecS, RecL: TRect;
begin
RecS := Rect(Screen.Width, Screen.Height, Screen.Width, Screen.Height);
RecL := ThisForm.BoundsRect;
DrawAnimatedRects(GetDesktopWindow, IDANI_CAPTION, RecS, RecL);
{ ... }
end;
In FormHide:
var
RecS, RecL: TRect;
begin
HideTimer.Enabled := False;
RecS := Rect(Screen.Width, Screen.Height, Screen.Width, Screen.Height);
RecL := ThisForm.BoundsRect;
DrawAnimatedRects(GetDesktopWindow, IDANI_CAPTION, RecL, RecS);
end;
Взято с
Delphi Knowledge BaseКак сделать анимацию немерцающей
Как сделать анимацию немерцающей
Мерцание возникает, когда цвет точки меняется два раза подряд. Например, правильнее объект при его перемещении стирать и затем рисовать на новом месте не на экране, а в памяти, и выводить на форму уже готовое изображение поверх предыдущего. В таком случае смена цветов на экране происходит только один раз.
var
bm: TBitMap;
procedure TForm1.FormCreate(Sender: TObject);
begin
bm := TBitMap.Create;
bm.Width := Form1.ClientWidth;
bm.Height := Form1.ClientHeight;
with bm.Canvas do
begin
Font.name := 'Arial';
Font.Size := 50;
Font.Color := clBlue;
end;
Timer1.Interval := 100;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
s: string;
Hour, Min, Sec, MSec: Word;
begin
DecodeTime(Time, Hour, Min, Sec, MSec);
with bm.Canvas do
begin
Brush.Style := bsSolid;
Brush.Color := clWhite;
FillRect(ClipRect);
s := TimeToStr(Time);
TextOut((bm.Width - TextWidth(s)) div 2,
(bm.Height - TextHeight(s)) div 2, s);
Pen.Mode := pmMask;
Pen.Width := 20;
Pen.Color := clLime;
Brush.Style := bsClear;
Rectangle(bm.Width div 2 - (MSec * bm.Width) div 5000,
bm.Height div 2 - (MSec * bm.Height) div 5000,
bm.Width div 2 + (MSec * bm.Width) div 5000,
bm.Height div 2 + (MSec * bm.Height) div 5000);
end;
Form1.Canvas.Draw(0, 0, bm);
end;
Взято с
Как сделать balloon tooltips?
Как сделать balloon tooltips?
uses
Commctrl;
procedure ShowBalloonTip(Control: TWinControl; Icon: integer; Title: pchar; Text: PWideChar;
BackCL, TextCL: TColor);
const
TOOLTIPS_CLASS = 'tooltips_class32';
TTS_ALWAYSTIP = $01;
TTS_NOPREFIX = $02;
TTS_BALLOON = $40;
TTF_SUBCLASS = $0010;
TTF_TRANSPARENT = $0100;
TTF_CENTERTIP = $0002;
TTM_ADDTOOL = $0400 + 50;
TTM_SETTITLE = (WM_USER + 32);
ICC_WIN95_CLASSES = $000000FF;
type
TOOLINFO = packed record
cbSize: Integer;
uFlags: Integer;
hwnd: THandle;
uId: Integer;
rect: TRect;
hinst: THandle;
lpszText: PWideChar;
lParam: Integer;
end;
var
hWndTip: THandle;
ti: TOOLINFO;
hWnd: THandle;
begin
hWnd := Control.Handle;
hWndTip := CreateWindow(TOOLTIPS_CLASS, nil,
WS_POPUP or TTS_NOPREFIX or TTS_BALLOON or TTS_ALWAYSTIP,
0, 0, 0, 0, hWnd, 0, HInstance, nil);
if hWndTip <> 0 then
begin
SetWindowPos(hWndTip, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
ti.cbSize := SizeOf(ti);
ti.uFlags := TTF_CENTERTIP or TTF_TRANSPARENT or TTF_SUBCLASS;
ti.hwnd := hWnd;
ti.lpszText := Text;
Windows.GetClientRect(hWnd, ti.rect);
SendMessage(hWndTip, TTM_SETTIPBKCOLOR, BackCL, 0);
SendMessage(hWndTip, TTM_SETTIPTEXTCOLOR, TextCL, 0);
SendMessage(hWndTip, TTM_ADDTOOL, 1, Integer(@ti));
SendMessage(hWndTip, TTM_SETTITLE, Icon mod 4, Integer(Title));
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowBalloonTip(Button1, 1, 'Title',
'Balloon tooltip,http://kingron.myetang.com; updated by Calin', clBlue, clNavy);
end;
{....}
uses Commctrl;
{....}
const
TTS_BALLOON = $40;
TTM_SETTITLE = (WM_USER + 32);
var
hTooltip: Cardinal;
ti: TToolInfo;
buffer : array[0..255] of char;
{....}
procedure CreateToolTips(hWnd: Cardinal);
begin
hToolTip := CreateWindowEx(0, 'Tooltips_Class32', nil, TTS_ALWAYSTIP or TTS_BALLOON,
Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT),
Integer(CW_USEDEFAULT), hWnd, 0, hInstance, nil);
if hToolTip <> 0 then
begin
SetWindowPos(hToolTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or
SWP_NOSIZE or SWP_NOACTIVATE);
ti.cbSize := SizeOf(TToolInfo);
ti.uFlags := TTF_SUBCLASS;
ti.hInst := hInstance;
end;
end;
procedure AddToolTip(hwnd: DWORD; lpti: PToolInfo; IconType: Integer;
Text, Title: PChar);
var
Item: THandle;
Rect: TRect;
begin
Item := hWnd;
if (Item <> 0) and (GetClientRect(Item, Rect)) then
begin
lpti.hwnd := Item;
lpti.Rect := Rect;
lpti.lpszText := Text;
SendMessage(hToolTip, TTM_ADDTOOL, 0, Integer(lpti));
FillChar(buffer, SizeOf(buffer), #0);
lstrcpy(buffer, Title);
if (IconType > 3) or (IconType < 0) then IconType := 0;
SendMessage(hToolTip, TTM_SETTITLE, IconType, Integer(@buffer));
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
CreateToolTips(Form1.Handle);
AddToolTip(Memo1.Handle, @ti, 1, 'Tooltip text', 'Title');
end;
{
IconType can be:
0 - No icon
1 - Information
2 - Warning
3 - Error
}
Взято с сайта
Как сделать, чтобы форма закрывалась при нажатии Esc?
Как сделать, чтобы форма закрывалась при нажатии Esc?
Для начала необходимо установить свойство формы KeyPreview в True. А потом уже можно отлавливать "Esc":
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.KeyPreview := True;
end;
procedure TForm1.FormKeyPress
(Sender: TObject; var Key: Char);
begin
if key = #27 then Close;
end;
Взято с Исходников.ru
Как сделать, чтобы компоненты отбрасывали тень?
Как сделать, чтобы компоненты отбрасывали тень?
procedure ShadeIt(f: TForm; c: TControl; Width: Integer; Color: TColor);
var
rect: TRect;
old: TColor;
begin
if (c.Visible) then
begin
rect := c.BoundsRect;
rect.Left := rect.Left + Width;
rect.Top := rect.Top + Width;
rect.Right := rect.Right + Width;
rect.Bottom := rect.Bottom + Width;
old := f.Canvas.Brush.Color;
f.Canvas.Brush.Color := Color;
f.Canvas.fillrect(rect);
f.Canvas.Brush.Color := old;
end;
end;
procedure TForm1.FormPaint(Sender: TObject);
var
i: Integer;
begin
for i := 0 to Self.ControlCount - 1 do
ShadeIt(Self, Self.Controls[i], 3, clBlack);
end;
Взято с сайта
Как сделать чтобы окно было на весь экран?
Как сделать чтобы окно было на весь экран?
PostMessage(Application.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 1);
Автор ответа: Baa
Взято с Vingrad.ru
Как сделать, чтобы TEdit воспринимал одни цифры и DecimalSeparator?
Как сделать, чтобы TEdit воспринимал одни цифры и DecimalSeparator?
Автор: Full ( http://full.hotmail.ru/ )
type
TNumEdit = class(TEdit)
procedure CreateParams(var Params: TCreateParams); override;
procedure KeyPress(var Key: Char); override;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Standard', [TNumEdit]);
end;
procedure TNumEdit.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style or ES_MULTILINE or ES_RIGHT;
end;
procedure TNumEdit.KeyPress(var Key: Char);
begin
case key of
'0'..'9': ; // цифры
#8: ; // забой
'.', ',': if Pos(DecimalSeparator, Text)=0 then Key:=DecimalSeparator else Key:=#0; // десятичный разделитель
else key:=#0;
end; // case
end;
end.
Взято с Исходников.ru
Как сделать, чтобы запускалась только одна копия приложения?
Как сделать, чтобы запускалась только одна копия приложения?
varAtomText: array[0..31] of Char;
procedure LookForPreviousInstance;
var
PreviousInstanceWindow : hWnd;
AppName : array[0..30] of char;
FoundAtom : TAtom;
begin
// помещаем имя приложения в AtomText
StrFmt(AtomText, 'OnlyOne%s', [Copy(Application.Title,1,20)]);
// Проверяем, не создано ли уже атома с таким именем приложения
FoundAtom := GlobalFindAtom(AtomText);
if FoundAtom <> 0 then // эта копия приложения уже запущена
begin
StrFmt(AppName,'%s', [Application.Title]);
// изменяем текущий заголовок, чтобы FindWindow не видела его
Application.ShowMainForm := false;
Application.Title := 'destroy me';
// ищем предыдущую копию приложения
PreviousInstanceWindow := FindWindow(nil,AppName);
// Передаём фокус на предыдущую копию приложения
// завершаем текущую копию
Application.Terminate;
if PreviousInstanceWindow <> 0 then
if IsIconic(PreviousInstanceWindow) then
ShowWindow(PreviousInstanceWindow,SW_RESTORE)
else SetForegroundWindow(PreviousInstanceWindow);
end;
// создаём глобальный атом, чтобы предотвратить запуск другой копии приложения
FoundAtom := GlobalAddAtom(AtomText);
end;
constructor TForm.Create(AOwner: TComponent);
begin
inherited;
LookForPreviousInstance;
...
end;
destructor TForm.Destroy;
var
FoundAtom : TAtom;
ValueReturned : word;
begin
// не забудьте удалить глобальный атом
FoundAtom := GlobalFindAtom(AtomText);
if FoundAtom <> 0 then ValueReturned := GlobalDeleteAtom(FoundAtom);
inherited Destroy;
end;
Взято с Исходников.ru
В блоке begin..end модуля .dpr:
begin
if HPrevInst <> 0 then
begin
ActivatePreviousInstance;
Halt;
end;
end;
Реализация:
unit PrevInst;
interface
uses
WinProcs,
WinTypes,
SysUtils;
type
PHWnd = ^HWnd;
function EnumApps(Wnd: HWnd; TargetWindow: PHWnd): bool; export;
procedure ActivatePreviousInstance;
implementation
function EnumApps(Wnd: HWnd; TargetWindow: PHWnd): bool;
var
ClassName: array[0..30] of char;
begin
Result := true;
if GetWindowWord(Wnd, GWW_HINSTANCE) = HPrevInst then
begin
GetClassName(Wnd, ClassName, 30);
if STRIComp(ClassName, 'TApplication') = 0 then
begin
TargetWindow^ := Wnd;
Result := false;
end;
end;
end;
procedure ActivatePreviousInstance;
var
PrevInstWnd: HWnd;
begin
PrevInstWnd := 0;
EnumWindows(@EnumApps, LongInt(@PrevInstWnd));
if PrevInstWnd <> 0 then
if IsIconic(PrevInstWnd) then
ShowWindow(PrevInstWnd, SW_Restore)
else
BringWindowToTop(PrevInstWnd);
end;
end.
Взято из
Советов по Delphi от
Сборник Kuliba
Как сделать colorize?
Как сделать colorize?
functionColorize(RGB, Luma: Cardinal);
var
l, r, g, b: Single;
begin
Result := Luma;
if Luma = 0 then { it's all black anyway}
Exit;
l := Luma / 255;
r := RGB and $FF * l;
g := RGB shr 8 and $FF * l;
b := RGB shr 16 and $FF * l;
Result := Round(b) shl 16 or Round(g) shl 8 or Round(r);
end;
Взято с
Delphi Knowledge BaseКак сделать дырку в окне?
Как сделать дырку в окне?
procedure TForm1.Button4Click(Sender: TObject);
var
HRegion1, Hreg2, Hreg3: THandle;
Col: TColor;
begin
ShowMessage ('Ready for a real crash?');
Col := Color;
Color := clRed;
PlaySound ('boom.wav', 0, snd_sync);
HRegion1 := CreatePolygonRgn (Pts,
sizeof (Pts) div 8,
alternate);
SetWindowRgn (
Handle, HRegion1, True);
ShowMessage ('Now, what have you done?');
Color := Col;
ShowMessage ('Вам лучше купить новый монитор');
end;
Взято с Исходников.ru
Как сделать фон у текста прозрачным?
Как сделать фон у текста прозрачным?
Для этого можно воспользоваться API функцией SetBkMode().
procedure TForm1.Button1Click(Sender: TObject);
var
OldBkMode : integer;
begin
with Form1.Canvas do begin
Brush.Color := clRed;
FillRect(Rect(0, 0, 100, 100));
Brush.Color := clBlue;
TextOut(10, 20, 'Not Transparent!');
OldBkMode := SetBkMode(Handle, TRANSPARENT);
TextOut(10, 50, 'Transparent!');
SetBkMode(Handle, OldBkMode);
end;
end;
Взято с Исходников.ru
Как сделать форму без caption?
Как сделать форму без caption?
Обычная форма:
TForm.Style:=bsNone
Автор ответа: Song
Взято с Vingrad.ru
MDIChild форма:
setWindowLong (handle,GWL_STYLE,getWindowLong(handle, GWL_STYLE) and not WS_CAPTION);
width:=width+1;
width:=width-1;
Автор ответа: rhf
Взято с Vingrad.ru
{ Private Declaration }
procedure CreateParams(var Params : TCreateParams); override;
...
procedure TForm1.CreateParams(var Params : TCreateParams);
begin
inherited Createparams(Params);
with Params do
Style := (Style or WS_POPUP) and not WS_DLGFRAME;
end;
Взято с Исходников.ru
Как сделать графический hint?
Как сделать графический hint?
{*********************************************************
Mit Hilfe des folgendes Codes lassen sich leicht beliebige
Hints erstellen. Dazu muss nur dir Prozedur "Paint" den
Wьnschen entsprechend angepasst werden.
With the following Code you can simply create custom hints.
You just have to change the procedur "Paint".
*********************************************************}
type
TGraphicHintWindow = class(THintWindow)
constructor Create(AOwner: TComponent); override;
private
FActivating: Boolean;
public
procedure ActivateHint(Rect: TRect; const AHint: string); override;
protected
procedure Paint; override;
published
property Caption;
end;
{...}
constructor TGraphicHintWindow.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
{
Hier kцnnen beliebige Schrift Eigenschaften gesetzt
werden.
Here you can set custom Font Properties:
}
with Canvas.Font do
begin
Name := 'Arial';
Style := Style + [fsBold];
Color := clBlack;
end;
end;
procedure TGraphicHintWindow.Paint;
var
R: TRect;
bmp: TBitmap;
begin
R := ClientRect;
Inc(R.Left, 2);
Inc(R.Top, 2);
{*******************************************************
Der folgende Code ist ein Beispiel wie man die Paint
Prozedur nutzen kann um einen benutzerdefinierten Hint
zu erzeugen.
The folowing Code ist an example how to create a custom
Hint Object. :
}
bmp := TBitmap.Create;
bmp.LoadfromFile('D:\hint.bmp');
with Canvas do
begin
Brush.Style := bsSolid;
Brush.Color := clsilver;
Pen.Color := clgray;
Rectangle(0, 0, 18, R.Bottom + 1);
Draw(2,(R.Bottom div 2) - (bmp.Height div 2), bmp);
end;
bmp.Free;
//Beliebige HintFarbe
//custom Hint Color
Color := clWhite;
Canvas.Brush.Style := bsClear;
Canvas.TextOut(20, (R.Bottom div 2) - (Canvas.Textheight(Caption) div 2), Caption);
{********************************************************}
end;
procedure TGraphicHintWindow.ActivateHint(Rect: TRect; const AHint: string);
begin
FActivating := True;
try
Caption := AHint;
//Hцhe des Hints setzen setzen
//Set the "Height" Property of the Hint
Inc(Rect.Bottom, 14);
//Breite des Hints setzen
//Set the "Width" Property of the Hint
Rect.Right := Rect.Right + 20;
UpdateBoundsRect(Rect);
if Rect.Top + Height > Screen.DesktopHeight then
Rect.Top := Screen.DesktopHeight - Height;
if Rect.Left + Width > Screen.DesktopWidth then
Rect.Left := Screen.DesktopWidth - Width;
if Rect.Left < Screen.DesktopLeft then Rect.Left := Screen.DesktopLeft;
if Rect.Bottom < Screen.DesktopTop then Rect.Bottom := Screen.DesktopTop;
SetWindowPos(Handle, HWND_TOPMOST, Rect.Left, Rect.Top, Width, Height,
SWP_SHOWWINDOW or SWP_NOACTIVATE);
Invalidate;
finally
FActivating := False;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
HintWindowClass := TGraphicHintWindow;
Application.ShowHint := False;
Application.ShowHint := True;
end;
Взято с сайта
Как сделать greyscale dithering?
Как сделать greyscale dithering?
procedureGreyscale(dib8, dib24: TFastDIB; Colors: Byte);
type
TDiv3 = array[0..767] of Byte;
TScale = array[0..255] of Byte;
TLineErrors = array[-1.. - 1] of DWord;
PDiv3 = ^TDiv3;
PScale = ^TScale;
PLineErrors = ^TLineErrors;
var
x, y, i, Ln, Nxt: Integer;
pc: PFColor;
pb: PByte;
Lines: array[0..1] of PLineErrors;
Div3: PDiv3;
Scale: PScale;
pti: PDWord;
dir: ShortInt;
begin
dib8.FillColors(0, Colors, tfBlack, tfWhite);
New(Div3);
pb := Pointer(Div3);
for i := 0 to 255 do
begin
pb^ := i;
Inc(pb);
pb^ := i;
Inc(pb);
pb^ := i;
Inc(pb);
end;
New(Scale);
pb := Pointer(Scale);
x := (Colors shl 16) shr 8;
y := x;
for i := 0 to 255 do
begin
pb^ := y shr 16;
Inc(y, x);
Inc(pb);
end;
GetMem(Lines[0], 24 * (dib24.Width + 2));
GetMem(Lines[1], 24 * (dib24.Width + 2));
pc := PFColor(dib24.Bits);
for x := 0 to dib24.Width - 1 do
begin
Lines[0, x] := Div3[pc.r + pc.g + pc.b] * 16;
Inc(pc);
end;
pc := Ptr(Integer(pc) + dib24.Gap);
dir := 1;
for y := 1 to dib24.Height do
begin
Nxt := y mod 2;
Ln := 1 - Nxt;
if y < dib24.Height then
begin
for x := 0 to dib24.Width - 1 do
begin
Lines[Nxt, x] := Div3[pc.r + pc.g + pc.b] * 16;
Inc(pc);
end;
pc := Ptr(Integer(pc) + dib24.Gap);
end;
x := 0;
if dir = -1 then
x := dib24.Width - 1;
pti := @Lines[Ln, x];
pb := @dib8.Pixels8[y - 1, x];
while ((x > -1) and (x < dib24.Width)) do
begin
pti^ := pti^ div 16;
if pti^ > 255 then
pti^ := 255
else if pti^ < 0 then
pti^ := 0;
pb^ := Scale[pti^];
i := pti^ - dib8.Colors[pb^].r;
if i <> 0 then
begin
Inc(Lines[Ln, x + dir], i * 7);
Inc(Lines[Nxt, x - dir], i * 3);
Inc(Lines[Nxt, x], i * 5);
Inc(Lines[Nxt, x + dir], i);
end;
Inc(pb, dir);
Inc(pti, dir);
Inc(x, dir);
end;
Inc(pb, dib8.Gap);
dir := -dir;
end;
Dispose(Lines[0]);
Dispose(Lines[1]);
Dispose(Scale);
Dispose(Div3);
end;
Взято с
Delphi Knowledge BaseКак сделать экспорт TDataSet в XML file?
Как сделать экспорт TDataSet в XML file?
{Unit to export a dataset to XML}
unit DS2XML;
interface
uses
Classes, DB;
procedure DatasetToXML(Dataset: TDataSet; FileName: string);
implementation
uses
SysUtils;
var
SourceBuffer: PChar;
procedure WriteString(Stream: TFileStream; s: string);
begin
StrPCopy(SourceBuffer, s);
Stream.Write(SourceBuffer[0], StrLen(SourceBuffer));
end;
procedure WriteFileBegin(Stream: TFileStream; Dataset: TDataSet);
function XMLFieldType(fld: TField): string;
begin
case fld.DataType of
ftString: Result := '"string" WIDTH="' + IntToStr(fld.Size) + '"';
ftSmallint: Result := '"i4"'; //??
ftInteger: Result := '"i4"';
ftWord: Result := '"i4"'; //??
ftBoolean: Result := '"boolean"';
ftAutoInc: Result := '"i4" SUBTYPE="Autoinc"';
ftFloat: Result := '"r8"';
ftCurrency: Result := '"r8" SUBTYPE="Money"';
ftBCD: Result := '"r8"'; //??
ftDate: Result := '"date"';
ftTime: Result := '"time"'; //??
ftDateTime: Result := '"datetime"';
else
end;
if fld.Required then
Result := Result + ' required="true"';
if fld.ReadOnly then
Result := Result + ' readonly="true"';
end;
var
i: Integer;
begin
WriteString(Stream, '<?xml version="1.0" standalone="yes"?><!-- Generated by SMExport --> ' +
'<DATAPACKET Version="2.0">');
WriteString(Stream, '<METADATA><FIELDS>');
{write th metadata}
with Dataset do
for i := 0 to FieldCount - 1 do
begin
WriteString(Stream, '<FIELD attrname="' +
Fields[i].FieldName +
'" fieldtype=' +
XMLFieldType(Fields[i]) +
'/>');
end;
WriteString(Stream, '</FIELDS>');
WriteString(Stream, '<PARAMS DEFAULT_ORDER="1" PRIMARY_KEY="1" LCID="1033"/>');
WriteString(Stream, '</METADATA><ROWDATA>');
end;
procedure WriteFileEnd(Stream: TFileStream);
begin
WriteString(Stream, '</ROWDATA></DATAPACKET>');
end;
procedure WriteRowStart(Stream: TFileStream; IsAddedTitle: Boolean);
begin
if not IsAddedTitle then
WriteString(Stream, '<ROW');
end;
procedure WriteRowEnd(Stream: TFileStream; IsAddedTitle: Boolean);
begin
if not IsAddedTitle then
WriteString(Stream, '/>');
end;
procedure WriteData(Stream: TFileStream; fld: TField; AString: ShortString);
begin
if Assigned(fld) and (AString <> '') then
WriteString(Stream, ' ' + fld.FieldName + '="' + AString + '"');
end;
function GetFieldStr(Field: TField): string;
function GetDig(i, j: Word): string;
begin
Result := IntToStr(i);
while (Length(Result) < j) do
Result := '0' + Result;
end;
var
Hour, Min, Sec, MSec: Word;
begin
case Field.DataType of
ftBoolean: Result := UpperCase(Field.AsString);
ftDate: Result := FormatDateTime('yyyymmdd', Field.AsDateTime);
ftTime: Result := FormatDateTime('hhnnss', Field.AsDateTime);
ftDateTime:
begin
Result := FormatDateTime('yyyymmdd', Field.AsDateTime);
DecodeTime(Field.AsDateTime, Hour, Min, Sec, MSec);
if (Hour <> 0) or (Min <> 0) or (Sec <> 0) or (MSec <> 0) then
Result := Result + 'T' + GetDig(Hour, 2) + ':' + GetDig(Min,
2) + ':' + GetDig(Sec, 2) + GetDig(MSec, 3);
end;
else
Result := Field.AsString;
end;
end;
procedure DatasetToXML(Dataset: TDataSet; FileName: string);
var
Stream: TFileStream;
bkmark: TBookmark;
i: Integer;
begin
Stream := TFileStream.Create(FileName, fmCreate);
SourceBuffer := StrAlloc(1024);
WriteFileBegin(Stream, Dataset);
with DataSet do
begin
DisableControls;
bkmark := GetBookmark;
First;
{write a title row}
WriteRowStart(Stream, True);
for i := 0 to FieldCount - 1 do
WriteData(Stream, nil, Fields[i].DisplayLabel);
{write the end of row}
WriteRowEnd(Stream, True);
while (not EOF) do
begin
WriteRowStart(Stream, False);
for i := 0 to FieldCount - 1 do
WriteData(Stream, Fields[i], GetFieldStr(Fields[i]));
{write the end of row}
WriteRowEnd(Stream, False);
Next;
end;
GotoBookmark(bkmark);
EnableControls;
end;
WriteFileEnd(Stream);
Stream.Free;
StrDispose(SourceBuffer);
end;
end.
//Beispiel, Example:
uses DS2XML;
procedure TForm1.Button1Click(Sender: TObject);
begin DatasetToXML(Table1, 'test.xml');
end;
Взято с сайта
Как сделать картинки из TImageList прозрачными?
Как сделать картинки из TImageList прозрачными?
procedure TForm1.Button1Click(Sender: TObject);
var
bm: TBitmap;
il: TImageList;
begin
bm := TBitmap.Create;
bm.LoadFromFile('C:\DownLoad\TEST.BMP');
il := TImageList.CreateSize(bm.Width, bm.Height);
il.DrawingStyle := dsTransparent;
il.Masked := true;
il.AddMasked(bm, clRed);
il.Draw(Form1.Canvas, 0, 0, 0);
bm.Free;
il.Free;
end;
Как сделать MDI-приложение, где сливаются меню дочернего и главного окна, и полосы инструментов?
Как сделать MDI-приложение, где сливаются меню дочернего и главного окна, и полосы инструментов?
Ваpиант 1. CoolBar.
procedureTMainForm.SetBands(AControls: array of TWinControl;
ABreaks: array of boolean);
var
i: integer;
begin
with CoolBar do
begin
for i:=0 to High(AControls) do
begin
if Bands.Count=succ(i) then
TCoolBand.Create(Bands);
with Bands[succ(i)] do
begin
if Assigned(Control) then
Control.Hide;
MinHeight:=AControls[i].Height;
Break:=ABreaks[i];
Control:=AControls[i];
Control.Show;
Visible:=true;
end
end;
for i:=High(AControls)+2 to pred(Bands.Count) do
Bands[i].Free
end
end;
и
procedure TMsgForm.FormActivate(Sender: TObject);
begin
MainForm.SetBands([ToolBar],[false])
end;
Пpимечание:
Оба массива pавны по длине. CoolBar.Bands[0] должен существовать всегда,.. на нём я pазмешаю "глобальные" кнопки. СoolBar[1] тоже можно сделать в DesignTime с Break:=false и пpидвинуть поближе с началу. Пpи CoolBar.AutoSize:=true возможно "мигании" (пpи добавлении на новую стpоку) так что можно добавить:
AutoSize := false;
try
...
finally
AutoSize := true;
TMainForm
...
object SpeedBar: TPanel
...
Align = alTop
BevelOuter = bvNone
object ToolBar: TPanel
...
Align = alLeft
BevelOuter = bvNone
end
object RxSplitter1: TRxSplitter
...
ControlFirst = ToolBar
ControlSecond = ChildBar
Align = alLeft
BevelOuter = bvLowered
end
object ChildBar: TPanel
...
Align = alClient
BevelOuter = bvNone
end
end
TMdiChild {пpородитель всех остальных}
...
object pnToolBar: TPanel
...
Align = alTop
BevelOuter = bvNone
Visible = False
end
procedure TMDIForm.FormActivate(Sender: TObject);
begin
pnToolBar.Parent := MainForm.ChildBar;
pnToolBar.Visible := True;
end;
procedure TMDIForm.FormDeactivate(Sender: TObject);
begin
pnToolBar.Visible := false;
pnToolBar.Parent := self
end;
Взято с
Как сделать Memo с закруглёнными краями?
Как сделать Memo с закруглёнными краями?
procedureTForm1.Button1Click(Sender: TObject);
var
rgn: HRGN;
r: TRect;
begin
r := memo1.ClientRect;
rgn := CreateRoundRectRgn(r.Left, r.top, r.right, r.bottom, 20, 20);
memo1.BorderStyle := bsNone;
memo1.Perform(EM_GETRECT, 0, lparam(@r));
InflateRect(r, -5, -5);
memo1.Perform(EM_SETRECTNP, 0, lparam(@r));
SetWindowRgn(memo1.Handle, rgn, true);
end;
Взято с
Delphi Knowledge BaseКак сделать меню как в Дельфи?
Как сделать меню как в Дельфи?
1. Разместите на форме TControlBar. (закладка Additional) Установите Align = Client.
2. Разместите TToolBar (закладка Win32) внутри TControlBar.
3. Установите в True свойства Flat и ShowCaptions этого TToolBar.
4. Создайте на TToolBar столько TToolButtons сколько Вам нужно. (щелкнув по TToolBar
правой кнопкой и выбрав NewButton)
5. Установите свойство Grouped = True для всех TToolButtons. Это позволит меню выпадать
при перемещении курсора между главными пунктами меню (если меню уже показано).
6. Разместите на фоме TMainMenu и убедитесь, что оно *НЕ присоденено* как меню главной
формы. (посмотрите свойство Menu формы).
7. Создайте все пункты меню (щелкнув по TMainMenu кнопкой и выбрав Menu Designer)
8. Для каждой TToolButton установите ее MenuItem равным соответсвующему пункту TMainMenu.
Взято из
DELPHI VCL FAQ
Перевод с английского Подборку, перевод и адаптацию материала подготовил Aziz(JINX)
специально для
Как сделать многострочную надпись на TBitBtn?
Как сделать многострочную надпись на TBitBtn?
Выводите текст надписи непосредственно на "glyph" TBitBtn'а
procedure TForm1.FormCreate(Sender: TObject);
var
R: TRect;
N: Integer;
Buff: array[0..255] of Char;
begin
with BitBtn1 do
begin
Caption := 'A really really long caption';
Glyph.Canvas.Font := Self.Font;
Glyph.Width := Width - 6;
Glyph.Height := Height - 6;
R := Bounds(0, 0, Glyph.Width, 0);
StrPCopy(Buff, Caption);
Caption := '';
DrawText(Glyph.Canvas.Handle, Buff, StrLen(Buff), R,
DT_CENTER or DT_WORDBREAK or DT_CALCRECT);
OffsetRect(R, (Glyph.Width - R.Right) div 2,
(Glyph.Height - R.Bottom) div 2);
DrawText(Glyph.Canvas.Handle, Buff, StrLen(Buff), R,
DT_CENTER or DT_WORDBREAK);
end;
end;
Как сделать mount?
Как сделать mount?
{
The following example shows a Linux-Console application, which mount
the floppy.
}
program Project1;
{$APPTYPE CONSOLE}
uses
Libc;
begin
if mount('/dev/fd0', '/mnt/floppy', 'vfat', MS_RDONLY, nil) = -1 then
WriteLn('Mount return : ', Errno, '(', strerror(errno), ')')
else
WriteLn('Floppy mounted');
end.
Взято с сайта