1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
743.
744.
745.
746.
747.
748.
749.
750.
751.
752.
753.
754.
755.
756.
757.
758.
759.
760.
761.
762.
763.
764.
765.
766.
767.
768.
769.
770.
771.
772.
773.
774.
775.
776.
777.
778.
779.
780.
781.
782.
783.
784.
785.
786.
787.
788.
789.
790.
791.
792.
793.
794.
795.
796.
797.
798.
799.
800.
801.
802.
803.
804.
805.
806.
807.
808.
809.
810.
811.
812.
813.
814.
815.
816.
817.
818.
819.
820.
821.
822.
823.
824.
825.
826.
827.
828.
829.
830.
831.
832.
833.
834.
835.
836.
837.
838.
839.
840.
841.
842.
843.
844.
845.
846.
847.
848.
849.
850.
851.
852.
853.
854.
855.
856.
857.
858.
859.
860.
861.
862.
863.
864.
865.
866.
867.
868.
869.
870.
871.
872.
873.
874.
875.
876.
877.
878.
879.
880.
881.
882.
883.
884.
885.
886.
887.
888.
889.
890.
891.
892.
893.
894.
895.
896.
897.
898.
899.
900.
901.
902.
903.
904.
905.
906.
907.
908.
909.
910.
911.
912.
913.
914.
915.
916.
917.
918.
919.
920.
921.
922.
923.
924.
925.
926.
927.
928.
929.
930.
931.
932.
933.
934.
935.
936.
937.
938.
939.
940.
941.
942.
943.
944.
945.
946.
947.
948.
949.
950.
951.
952.
953.
954.
955.
956.
957.
958.
959.
960.
961.
962.
963.
964.
965.
966.
967.
968.
969.
970.
971.
972.
973.
974.
975.
976.
977.
978.
979.
980.
981.
982.
983.
984.
985.
986.
987.
988.
989.
990.
991.
992.
993.
994.
995.
996.
997.
998.
999.
1000.
1001.
1002.
1003.
1004.
1005.
1006.
1007.
1008.
1009.
1010.
1011.
1012.
1013.
1014.
1015.
1016.
1017.
1018.
1019.
1020.
1021.
1022.
1023.
1024.
1025.
1026.
1027.
1028.
1029.
1030.
1031.
1032.
1033.
1034.
1035.
1036.
1037.
1038.
1039.
1040.
1041.
1042.
1043.
1044.
1045.
1046.
1047.
1048.
1049.
1050.
1051.
1052.
1053.
1054.
1055.
1056.
1057.
1058.
1059.
1060.
1061.
1062.
1063.
1064.
1065.
1066.
1067.
1068.
1069.
1070.
1071.
1072.
1073.
1074.
1075.
1076.
1077.
1078.
1079.
1080.
1081.
1082.
1083.
1084.
1085.
1086.
1087.
1088.
1089.
1090.
1091.
1092.
1093.
1094.
1095.
1096.
1097.
1098.
1099.
1100.
1101.
1102.
1103.
1104.
1105.
1106.
1107.
1108.
1109.
1110.
1111.
1112.
1113.
1114.
1115.
1116.
1117.
1118.
1119.
1120.
1121.
1122.
1123.
1124.
1125.
1126.
1127.
1128.
1129.
1130.
1131.
1132.
1133.
1134.
1135.
1136.
1137.
1138.
1139.
1140.
1141.
1142.
1143.
1144.
1145.
1146.
1147.
1148.
1149.
1150.
1151.
1152.
1153.
1154.
1155.
1156.
1157.
1158.
1159.
1160.
1161.
1162.
1163.
1164.
1165.
1166.
1167.
1168.
1169.
1170.
1171.
1172.
1173.
1174.
1175.
1176.
1177.
1178.
1179.
1180.
1181.
1182.
1183.
1184.
1185.
1186.
1187.
1188.
1189.
1190.
1191.
1192.
1193.
1194.
1195.
1196.
1197.
1198.
1199.
1200.
1201.
1202.
1203.
1204.
1205.
1206.
1207.
1208.
1209.
1210.
1211.
1212.
1213.
1214.
1215.
1216.
1217.
1218.
1219.
1220.
1221.
1222.
1223.
1224.
1225.
1226.
1227.
1228.
1229.
1230.
1231.
1232.
1233.
1234.
1235.
1236.
1237.
1238.
1239.
1240.
1241.
1242.
1243.
1244.
1245.
1246.
1247.
1248.
1249.
1250.
1251.
1252.
1253.
1254.
1255.
1256.
1257.
1258.
1259.
1260.
1261.
1262.
1263.
1264.
1265.
1266.
1267.
1268.
1269.
1270.
1271.
1272.
1273.
1274.
1275.
1276.
1277.
1278.
1279.
1280.
1281.
1282.
1283.
1284.
1285.
1286.
1287.
1288.
1289.
1290.
1291.
1292.
1293.
1294.
1295.
1296.
1297.
1298.
1299.
1300.
1301.
1302.
1303.
1304.
1305.
1306.
1307.
1308.
1309.
1310.
1311.
1312.
1313.
1314.
1315.
1316.
1317.
1318.
1319.
1320.
1321.
1322.
1323.
1324.
1325.
1326.
1327.
1328.
1329.
1330.
1331.
1332.
1333.
1334.
1335.
1336.
1337.
1338.
1339.
1340.
1341.
1342.
1343.
1344.
1345.
1346.
1347.
1348.
1349.
1350.
1351.
1352.
1353.
1354.
1355.
1356.
1357.
1358.
1359.
1360.
1361.
1362.
1363.
1364.
1365.
1366.
1367.
1368.
1369.
1370.
1371.
1372.
1373.
1374.
1375.
1376.
1377.
1378.
1379.
1380.
1381.
1382.
1383.
1384.
1385.
1386.
1387.
1388.
1389.
1390.
1391.
1392.
1393.
1394.
1395.
1396.
1397.
1398.
1399.
1400.
1401.
1402.
1403.
1404.
1405.
1406.
1407.
1408.
1409.
1410.
1411.
1412.
1413.
1414.
1415.
1416.
1417.
1418.
1419.
1420.
1421.
1422.
1423.
1424.
1425.
1426.
1427.
1428.
1429.
1430.
1431.
1432.
1433.
1434.
1435.
1436.
1437.
1438.
1439.
1440.
1441.
1442.
1443.
1444.
1445.
1446.
1447.
1448.
1449.
1450.
1451.
1452.
1453.
1454.
1455.
1456.
1457.
1458.
1459.
1460.
1461.
1462.
1463.
1464.
1465.
1466.
1467.
1468.
1469.
1470.
1471.
1472.
1473.
1474.
1475.
1476.
1477.
1478.
1479.
1480.
1481.
1482.
1483.
1484.
1485.
1486.
1487.
1488.
1489.
1490.
1491.
1492.
1493.
1494.
1495.
1496.
1497.
1498.
1499.
1500.
1501.
1502.
1503.
1504.
1505.
1506.
1507.
1508.
1509.
1510.
1511.
1512.
1513.
1514.
1515.
1516.
1517.
1518.
1519.
1520.
1521.
1522.
1523.
1524.
1525.
1526.
1527.
1528.
1529.
1530.
1531.
1532.
1533.
1534.
1535.
1536.
1537.
1538.
1539.
1540.
1541.
1542.
1543.
1544.
1545.
1546.
1547.
1548.
1549.
1550.
1551.
1552.
1553.
1554.
1555.
1556.
1557.
1558.
1559.
1560.
1561.
1562.
1563.
1564.
1565.
1566.
1567.
1568.
1569.
1570.
1571.
1572.
1573.
1574.
1575.
1576.
1577.
1578.
1579.
1580.
1581.
1582.
1583.
1584.
1585.
1586.
1587.
1588.
1589.
1590.
1591.
1592.
1593.
1594.
1595.
1596.
1597.
1598.
1599.
1600.
1601.
1602.
1603.
1604.
1605.
1606.
1607.
1608.
1609.
1610.
1611.
1612.
1613.
1614.
1615.
1616.
1617.
1618.
1619.
1620.
1621.
1622.
1623.
1624.
1625.
1626.
1627.
1628.
1629.
1630.
1631.
1632.
1633.
1634.
1635.
1636.
1637.
1638.
1639.
1640.
1641.
1642.
1643.
1644.
1645.
1646.
1647.
1648.
1649.
1650.
1651.
1652.
1653.
1654.
1655.
1656.
1657.
1658.
1659.
1660.
1661.
1662.
1663.
1664.
1665.
1666.
1667.
1668.
1669.
1670.
1671.
1672.
1673.
1674.
1675.
1676.
1677.
1678.
1679.
1680.
1681.
1682.
1683.
1684.
1685.
1686.
1687.
1688.
1689.
1690.
1691.
1692.
1693.
1694.
1695.
1696.
1697.
1698.
1699.
1700.
1701.
1702.
1703.
1704.
1705.
1706.
1707.
1708.
1709.
1710.
1711.
1712.
1713.
1714.
1715.
1716.
1717.
1718.
1719.
1720.
1721.
1722.
1723.
1724.
1725.
1726.
1727.
1728.
1729.
1730.
1731.
1732.
1733.
1734.
1735.
1736.
1737.
1738.
1739.
1740.
1741.
1742.
1743.
1744.
1745.
1746.
1747.
1748.
1749.
1750.
1751.
1752.
1753.
1754.
1755.
1756.
1757.
1758.
1759.
1760.
1761.
1762.
1763.
1764.
1765.
1766.
1767.
1768.
1769.
1770.
1771.
1772.
1773.
1774.
1775.
1776.
1777.
1778.
1779.
1780.
1781.
1782.
1783.
1784.
1785.
1786.
1787.
1788.
1789.
1790.
1791.
1792.
1793.
1794.
1795.
1796.
1797.
1798.
1799.
1800.
1801.
1802.
1803.
1804.
1805.
1806.
1807.
1808.
1809.
1810.
1811.
1812.
1813.
1814.
1815.
1816.
1817.
1818.
1819.
1820.
1821.
1822.
1823.
1824.
1825.
1826.
1827.
1828.
1829.
1830.
1831.
1832.
1833.
1834.
1835.
1836.
1837.
1838.
1839.
1840.
1841.
1842.
1843.
1844.
1845.
1846.
1847.
1848.
1849.
1850.
1851.
1852.
1853.
1854.
1855.
1856.
1857.
1858.
1859.
1860.
1861.
1862.
1863.
1864.
1865.
1866.
1867.
1868.
1869.
1870.
1871.
1872.
1873.
1874.
1875.
1876.
1877.
1878.
1879.
1880.
1881.
1882.
1883.
1884.
1885.
1886.
1887.
1888.
1889.
1890.
1891.
1892.
1893.
1894.
1895.
1896.
1897.
1898.
1899.
1900.
1901.
1902.
1903.
1904.
1905.
1906.
1907.
1908.
1909.
1910.
1911.
1912.
1913.
1914.
1915.
1916.
1917.
1918.
1919.
1920.
1921.
1922.
1923.
1924.
1925.
1926.
1927.
1928.
1929.
1930.
1931.
1932.
1933.
1934.
1935.
1936.
1937.
1938.
1939.
1940.
1941.
1942.
1943.
1944.
1945.
1946.
1947.
1948.
1949.
1950.
1951.
1952.
1953.
1954.
1955.
1956.
1957.
1958.
1959.
1960.
1961.
1962.
1963.
1964.
1965.
1966.
1967.
1968.
1969.
1970.
1971.
1972.
1973.
1974.
1975.
1976.
1977.
1978.
1979.
1980.
1981.
1982.
1983.
1984.
1985.
1986.
1987.
1988.
1989.
1990.
1991.
1992.
1993.
1994.
1995.
1996.
1997.
1998.
1999.
2000.
2001.
2002.
2003.
2004.
2005.
2006.
2007.
2008.
2009.
2010.
2011.
2012.
2013.
2014.
2015.
2016.
2017.
2018.
2019.
2020.
2021.
2022.
2023.
2024.
2025.
2026.
2027.
2028.
2029.
2030.
2031.
2032.
2033.
2034.
2035.
2036.
2037.
2038.
2039.
2040.
2041.
2042.
2043.
2044.
2045.
2046.
2047.
2048.
2049.
2050.
2051.
2052.
2053.
2054.
2055.
2056.
2057.
2058.
2059.
2060.
2061.
2062.
2063.
2064.
2065.
2066.
2067.
2068.
2069.
2070.
2071.
2072.
2073.
2074.
2075.
2076.
2077.
2078.
2079.
2080.
2081.
2082.
2083.
2084.
2085.
2086.
2087.
2088.
2089.
2090.
2091.
2092.
2093.
2094.
2095.
2096.
2097.
2098.
2099.
2100.
2101.
2102.
2103.
2104.
2105.
2106.
2107.
2108.
2109.
2110.
2111.
2112.
2113.
2114.
2115.
2116.
2117.
2118.
2119.
2120.
2121.
2122.
2123.
2124.
2125.
2126.
2127.
2128.
2129.
2130.
2131.
2132.
2133.
2134.
2135.
2136.
2137.
2138.
2139.
2140.
2141.
2142.
2143.
2144.
2145.
2146.
2147.
2148.
2149.
2150.
2151.
2152.
2153.
2154.
2155.
2156.
2157.
2158.
2159.
2160.
2161.
2162.
2163.
2164.
2165.
2166.
2167.
2168.
2169.
2170.
2171.
2172.
2173.
2174.
2175.
2176.
2177.
2178.
2179.
2180.
2181.
2182.
2183.
2184.
2185.
2186.
2187.
2188.
2189.
2190.
2191.
2192.
2193.
2194.
2195.
2196.
2197.
2198.
2199.
2200.
2201.
2202.
2203.
2204.
2205.
2206.
2207.
2208.
2209.
2210.
2211.
2212.
2213.
2214.
2215.
2216.
2217.
2218.
2219.
2220.
2221.
2222.
2223.
2224.
2225.
2226.
2227.
2228.
2229.
2230.
2231.
2232.
2233.
2234.
2235.
2236.
2237.
2238.
2239.
2240.
2241.
2242.
2243.
2244.
2245.
2246.
2247.
2248.
2249.
2250.
2251.
2252.
2253.
2254.
2255.
2256.
2257.
2258.
2259.
2260.
2261.
2262.
2263.
2264.
2265.
2266.
2267.
2268.
2269.
2270.
2271.
2272.
2273.
2274.
2275.
2276.
2277.
2278.
2279.
2280.
2281.
2282.
2283.
2284.
2285.
2286.
2287.
2288.
2289.
2290.
2291.
2292.
2293.
2294.
2295.
2296.
2297.
2298.
2299.
2300.
2301.
2302.
2303.
2304.
2305.
2306.
2307.
2308.
2309.
2310.
2311.
2312.
2313.
2314.
2315.
2316.
2317.
2318.
2319.
2320.
2321.
2322.
2323.
2324.
2325.
2326.
2327.
2328.
2329.
2330.
2331.
2332.
2333.
2334.
2335.
2336.
2337.
2338.
2339.
2340.
2341.
2342.
2343.
2344.
2345.
2346.
2347.
2348.
2349.
2350.
2351.
2352.
2353.
2354.
2355.
2356.
2357.
2358.
2359.
2360.
2361.
2362.
2363.
2364.
2365.
2366.
2367.
2368.
2369.
2370.
2371.
2372.
2373.
2374.
2375.
2376.
2377.
2378.
2379.
2380.
2381.
2382.
2383.
2384.
2385.
2386.
2387.
2388.
2389.
2390.
2391.
2392.
2393.
2394.
2395.
2396.
2397.
2398.
2399.
2400.
2401.
2402.
2403.
2404.
2405.
2406.
2407.
2408.
2409.
2410.
2411.
2412.
2413.
2414.
2415.
2416.
2417.
2418.
2419.
2420.
2421.
2422.
2423.
2424.
2425.
2426.
2427.
2428.
2429.
2430.
2431.
2432.
2433.
2434.
2435.
2436.
2437.
2438.
2439.
2440.
2441.
2442.
2443.
2444.
2445.
2446.
2447.
2448.
2449.
2450.
2451.
2452.
2453.
2454.
2455.
2456.
2457.
2458.
2459.
2460.
2461.
2462.
2463.
2464.
2465.
2466.
2467.
2468.
2469.
2470.
2471.
2472.
2473.
2474.
2475.
2476.
2477.
2478.
2479.
2480.
2481.
2482.
2483.
2484.
2485.
2486.
2487.
2488.
2489.
2490.
2491.
2492.
2493.
2494.
2495.
2496.
2497.
2498.
2499.
2500.
2501.
2502.
2503.
2504.
2505.
2506.
2507.
2508.
2509.
2510.
2511.
2512.
2513.
2514.
2515.
2516.
2517.
2518.
2519.
2520.
2521.
2522.
2523.
2524.
2525.
2526.
2527.
2528.
2529.
2530.
2531.
2532.
2533.
2534.
2535.
2536.
2537.
2538.
2539.
2540.
2541.
2542.
2543.
2544.
2545.
2546.
2547.
2548.
2549.
2550.
2551.
2552.
2553.
2554.
2555.
2556.
2557.
2558.
2559.
2560.
2561.
2562.
2563.
2564.
2565.
2566.
2567.
2568.
2569.
2570.
2571.
2572.
2573.
2574.
2575.
2576.
2577.
2578.
2579.
2580.
2581.
2582.
2583.
2584.
2585.
2586.
2587.
2588.
2589.
2590.
2591.
2592.
2593.
2594.
2595.
2596.
2597.
2598.
2599.
2600.
2601.
2602.
2603.
2604.
2605.
2606.
2607.
2608.
2609.
2610.
2611.
2612.
2613.
2614.
2615.
2616.
2617.
2618.
2619.
2620.
2621.
2622.
2623.
2624.
2625.
2626.
2627.
2628.
2629.
2630.
2631.
2632.
2633.
2634.
2635.
2636.
2637.
2638.
2639.
2640.
2641.
2642.
2643.
2644.
2645.
2646.
2647.
2648.
2649.
2650.
2651.
2652.
2653.
2654.
2655.
2656.
2657.
2658.
2659.
2660.
2661.
2662.
2663.
2664.
2665.
2666.
2667.
2668.
2669.
2670.
2671.
2672.
2673.
2674.
2675.
2676.
2677.
2678.
2679.
2680.
2681.
2682.
2683.
2684.
2685.
2686.
2687.
2688.
2689.
2690.
2691.
2692.
2693.
2694.
2695.
2696.
2697.
2698.
2699.
2700.
2701.
2702.
2703.
2704.
2705.
2706.
2707.
2708.
2709.
2710.
2711.
2712.
2713.
2714.
2715.
2716.
2717.
2718.
2719.
2720.
2721.
2722.
2723.
2724.
2725.
2726.
2727.
2728.
2729.
2730.
2731.
2732.
2733.
2734.
2735.
2736.
2737.
2738.
2739.
2740.
2741.
2742.
2743.
2744.
2745.
2746.
2747.
2748.
2749.
2750.
2751.
2752.
2753.
2754.
2755.
2756.
2757.
2758.
2759.
2760.
2761.
2762.
2763.
2764.
2765.
2766.
2767.
2768.
2769.
2770.
2771.
2772.
2773.
2774.
2775.
2776.
2777.
2778.
2779.
2780.
2781.
2782.
2783.
2784.
2785.
2786.
2787.
2788.
2789.
2790.
2791.
2792.
2793.
2794.
2795.
2796.
2797.
2798.
2799.
2800.
2801.
2802.
2803.
2804.
2805.
2806.
2807.
2808.
2809.
2810.
2811.
2812.
2813.
2814.
2815.
2816.
2817.
2818.
2819.
2820.
2821.
2822.
2823.
2824.
2825.
2826.
2827.
2828.
2829.
2830.
2831.
2832.
2833.
2834.
2835.
2836.
2837.
2838.
2839.
2840.
2841.
2842.
2843.
2844.
2845.
2846.
2847.
2848.
2849.
2850.
2851.
2852.
2853.
2854.
2855.
2856.
2857.
2858.
2859.
2860.
2861.
2862.
2863.
2864.
2865.
2866.
2867.
2868.
2869.
2870.
2871.
2872.
2873.
2874.
2875.
2876.
2877.
2878.
2879.
2880.
2881.
2882.
2883.
2884.
2885.
2886.
2887.
2888.
2889.
2890.
2891.
2892.
2893.
2894.
2895.
2896.
2897.
2898.
2899.
2900.
2901.
2902.
2903.
2904.
2905.
2906.
2907.
2908.
2909.
2910.
2911.
2912.
2913.
2914.
2915.
2916.
2917.
2918.
2919.
2920.
2921.
2922.
2923.
2924.
2925.
2926.
2927.
2928.
2929.
2930.
2931.
2932.
2933.
2934.
2935.
2936.
2937.
2938.
2939.
2940.
2941.
2942.
2943.
2944.
2945.
2946.
2947.
2948.
2949.
2950.
2951.
2952.
2953.
2954.
2955.
2956.
2957.
2958.
2959.
2960.
2961.
2962.
2963.
2964.
2965.
2966.
2967.
2968.
2969.
2970.
2971.
2972.
2973.
2974.
2975.
2976.
2977.
2978.
2979.
2980.
2981.
2982.
2983.
2984.
2985.
2986.
2987.
2988.
2989.
2990.
2991.
2992.
2993.
2994.
2995.
2996.
2997.
2998.
2999.
3000.
3001.
3002.
3003.
3004.
3005.
3006.
3007.
3008.
3009.
3010.
3011.
3012.
3013.
3014.
3015.
3016.
3017.
3018.
3019.
3020.
3021.
3022.
3023.
3024.
3025.
3026.
3027.
3028.
3029.
3030.
3031.
3032.
3033.
3034.
3035.
3036.
3037.
3038.
3039.
3040.
3041.
3042.
3043.
3044.
3045.
3046.
3047.
3048.
3049.
3050.
3051.
3052.
3053.
3054.
3055.
3056.
3057.
3058.
3059.
3060.
3061.
3062.
3063.
3064.
3065.
3066.
3067.
3068.
3069.
3070.
3071.
3072.
3073.
3074.
3075.
3076.
3077.
3078.
3079.
3080.
3081.
3082.
3083.
3084.
3085.
3086.
3087.
3088.
3089.
3090.
3091.
3092.
3093.
3094.
3095.
3096.
3097.
3098.
3099.
3100.
3101.
3102.
3103.
3104.
3105.
3106.
3107.
3108.
3109.
3110.
3111.
3112.
3113.
3114.
3115.
3116.
3117.
3118.
3119.
3120.
3121.
3122.
3123.
3124.
3125.
3126.
3127.
3128.
3129.
3130.
3131.
3132.
3133.
3134.
3135.
3136.
3137.
3138.
3139.
3140.
3141.
3142.
3143.
3144.
3145.
3146.
3147.
3148.
3149.
3150.
3151.
3152.
3153.
3154.
3155.
3156.
3157.
3158.
3159.
3160.
3161.
3162.
3163.
3164.
3165.
3166.
3167.
3168.
3169.
3170.
3171.
3172.
3173.
3174.
3175.
3176.
3177.
3178.
3179.
3180.
3181.
3182.
3183.
3184.
3185.
3186.
3187.
3188.
3189.
3190.
3191.
3192.
3193.
3194.
3195.
3196.
3197.
3198.
3199.
3200.
3201.
3202.
3203.
3204.
3205.
3206.
3207.
3208.
3209.
3210.
3211.
3212.
3213.
3214.
3215.
3216.
3217.
3218.
3219.
3220.
3221.
3222.
3223.
3224.
3225.
3226.
3227.
3228.
3229.
3230.
3231.
3232.
3233.
3234.
3235.
3236.
3237.
3238.
3239.
3240.
3241.
3242.
3243.
3244.
3245.
3246.
Option Compare Database
Option Explicit
'1. `ПУТЬ К ВИНДУ (API)
'#########################
Private Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal p As String, ByVal p1 As Long) As Long
Dim windir As String
Private Sub Command1_Click()
windir = Space( 20 )
Text1.Text = Left(windir, GetWindowsDirectory(windir, 20 ))
End Sub
Private Sub Command1_Click()
Text1.Text = Environ("windir")
End Sub
'2.Скрыть/показать значки на Рабочем столе
'#########################
Private Declare Function ShowWindow& Lib "user32" (ByVal q&, ByVal q1&)
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal w As String, ByVal w1 As String) As Long
Dim r As Long
'Показываем
Private Sub Command1_Click()
r = FindWindow("progman", vbNullString)
Call ShowWindow(r, 1 )
End Sub
'Скрываем|
Private Sub Command2_Click()
r = FindWindow("progman", vbNullString)
Call ShowWindow(r, 0 )
End Sub
'3. Меняем рисунок на Рабочем столе
'#########################
Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal A As Long, ByVal a1 As Long, ByVal a2 As String, ByVal a3 As Long) As Long
Private Sub Command1_Click()
SystemParametersInfo 20 , 0 , "c:\as.bmp", True
End Sub
'4. Добовляем ссылку в Пуск/Документы
'#########################
Private Declare Function SHAddToRecentDocs Lib "shell32" (ByVal e As Long, ByVal e1 As String) As Long
Private Sub Command1_Click()
SHAddToRecentDocs 2 , "c:\as.bmp"
End Sub
'5. Устанавливаем курсор в любое место экрана
'#########################
Private Declare Function SetCursorPos Lib "user32" (ByVal r As Long, ByVal r1 As Long) As Long
Private Sub Command1_Click()
qqq = SetCursorPos( 66 , 77 )
End Sub
'6. Отслеживаем координаты мыши
'#########################
Type POINTAPI
X As Long
Y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" (AST As POINTAPI) As Long
Dim coord As POINTAPI
Private Sub Command1_Click()
q = GetCursorPos(coord)
Text1.Text = coord.X
Text2.Text = coord.Y
End Sub
'7. Работа с реестром
'#########################
Private Declare Function RegCreateKey Lib "advapi32" Alias "RegCreateKeyA" (ByVal Y As Long, ByVal y1 As String, y2 As Long) As Long
Private Declare Function RegOpenKeyExA Lib "advapi32" (ByVal u As Long, ByVal u1 As String, ByVal u2 As Long, ByVal u3 As Long, u4 As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32" (ByVal i As Long) As Long
Private Declare Function RegSetValueExA Lib "advapi32" (ByVal o As Long, ByVal o1 As String, ByVal o2 As Long, ByVal o4 As Long, ByVal o5 As String, ByVal o8 As Long) As Long
Dim A As Long
Dim s As Long
Const HKEY_LOCAL_MACHINE As Long = &H80000002
Private Sub Command1_Click()
A = RegCreateKey(HKEY_LOCAL_MACHINE, "Software\Microsoft\windows\CurrentVersion\Run\ZZZ", s)
End Sub
Private Sub Command2_Click()
A = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\Microsoft\windows\CurrentVersion\Run\ZZZ", 0 , HKEY_ALL_ACCESS, s)
A = RegSetValueExA(s, "Software\Microsoft\windows\CurrentVersion\Run\ZZZ", 0 , 1 , "gggg", 1 )
A = RegCloseKey(s)
End Sub
'8. Замораживаем Виндовз
'#########################
Private Declare Function SetPapent Lib "user32" (ByVal g As Long, ByVal g1 As Long) As Long
Dim f As Long
Private Sub Command1_Click()
f = SetPapent(Me.hwnd, Me.hwnd)
End Sub
'9. Установить заголовок всех активных окон
'#########################
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long
Public Sub WindowCaptionChangeAll(NewText As String)
For nI = 1 To 10000
Call SetWindowText(nI, NewText)
Next
End Sub
Private Sub Timer1_Timer()
WindowCaptionChangeAll ("Web-solyanka.narod.ru")
End Sub
'10. Скрыть/показать прогу от Ctrl+Alt+Del|
'#########################
Private Declare Function RegisterServiceProcess Lib "kernel32" (ByVal processID As Long, ByVal ServiceFlags As Long) As Long
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Sub Form_Load()
RegisterServiceProcess GetCurrentProcessId, 1
End Sub
Private Sub Form_Unload(Cancel As Integer)
RegisterServiceProcess GetCurrentProcessId, 0
End Sub
'11. Издать звук
'#########################
Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
Private Sub Command1_Click()
sndPlaySound "getpoint.wav", 1
End Sub
'12. Изменить метку диска/устройства
'#########################
Private Declare Function SetVolumeLabel Lib "kernel32" Alias "SetVolumeLabelA" (ByVal lpRootPathName As String, ByVal lpVolumeName As String) As Long
Private Sub Command1_Click()
'replace the "d:\" below with the drive you want to change its label
'replace the "MyNewLabel" below with the drive new label
If SetVolumeLabel("d:\", "MyNewLabel") = 0 Then
MsgBox "An Error occured while trying to change drive label", vbCritical, "Error"
End If
End Sub
'13. Обрушить твою прогу
'#########################
Private Declare Sub FatalAppExit Lib "kernel32" Alias "FatalAppExitA" (ByVal uAction As Long, ByVal lpMessageText As String)
Private Sub Form_Load()
FatalAppExit 0 , "Впишите сюда любой текст"
End Sub
'14. А вот как таскать форму не за заголовок, а за любое место?
'#########################
Const WM_NCLBUTTONDOWN = &HA1
Const HTCAPTION = 2
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, LParam As Any) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Call ReleaseCapture
Call SendMessage(Me.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0 &)
End Sub
'15. Очень часто спрашивают - как поместить форму поверх других форм
'#########################
'Поместите в модуль
Public Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
Public Const HWND_NOTOPMOST = - 2
Public Const HWND_TOPMOST = - 1
Public Const SWP_NOACTIVATE = &H10
Public Const SWP_NOMOVE = &H2
Public Const SWP_NOSIZE = &H1
Public Sub SetFormPosition(frmHandl As Long, TopPosition As Boolean)
If TopPosition Then
SetWindowPos frmHandl, HWND_TOPMOST, 0 , 0 , 0 , 0 , _
SWP_NOACTIVATE Or SWP_NOSIZE Or SWP_NOMOVE
Else
SetWindowPos frmHandl, HWND_NOTOPMOST, 0 , 0 , 0 , 0 , _
SWP_NOSIZE Or SWP_NOMOVE
End If
End Sub
'Поместите на форму в любой процедуре
Call SetFormPosition(Me.hwnd, True)
'16. Функция ExitWindowsEx
'#########################
Declare Function ExitWindowsEx Lib "user32.dll" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
'Платформа Win 95/98, Win NT
'ExitWindowsEx выключает или перезагружает компьютер.Функция возвращает 0 в случае ошибки и 1 в успешном случае.
uFlags
'Один или несколько флагов,определяющих способ выключения или перезагрузки компьютера:
EWX_FORCE = 4
'Закрывает все программы без приглашения сохранить файлы.
EWX_LOGOFF = 0
'Отключает от сети.
EWX_POWEROFF = 8
'Завершает работу системы и если есть возможность выключает компьютер.
EWX_REBOOT = 2
'Перезагружает компьютер.
EWX_SHUTDOWN = 1
'Завершает работу системы.
dwReserved
'Зарезервированный параметр для будущих версий Windows. Всегда установлен в 0.
Пример
' Перезагружаем компьютер, закрывая все открытые программы.
Dim RetVal As Long ' возвращаемое значение
RetVal = ExitWindowsEx(EWX_REBOOT Or EWX_FORCE, 0 )
If RetVal = 0 Then Debug.Print "Не удается перезагрузить компьютер."
'17. Определение разрешения и количества цветов дисплея
'#########################
Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long
Declare Function GetDesktopWindow Lib "user32" () As Long
Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Public Const HORZRES = 8
Public Const VERTRES = 10
Public Const BITSPIXEL = 12
Public Sub GetVideoMode(ByRef Width As Long, ByRef height As Long, ByRef Depth As Long)
Dim hdc As Long
hdc = GetDC(GetDesktopWindow())
Width = GetDeviceCaps(hdc, HORZRES)
height = GetDeviceCaps(hdc, VERTRES)
Depth = GetDeviceCaps(hdc, BITSPIXEL)
ReleaseDC GetDesktopWindow(), hdc
End Sub
'18. Как изменить текущее разрешение экрана
'#########################
Public Const DM_BITSPERPEL = &H40000
Public Const DM_PELSWIDTH = &H80000
Public Const DM_PELSHEIGHT = &H100000
Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32
Type DEVMODE
dmDeviceName As String * CCHDEVICENAME
dmSpecVersion As Integer
dmDriverVersion As Integer
dmSize As Integer
dmDriverExtra As Integer
dmFields As Long
dmOrientation As Integer
dmPaperSize As Integer
dmPaperLength As Integer
dmPaperWidth As Integer
dmScale As Integer
dmCopies As Integer
dmDefaultSource As Integer
dmPrintQuality As Integer
dmColor As Integer
dmDuplex As Integer
dmYResolution As Integer
dmTTOption As Integer
dmCollate As Integer
dmFormName As String * CCHFORMNAME
dmUnusedPadding As Integer
dmBitsPerPel As Integer
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
End Type
Declare Function ChangeDisplaySettings Lib "user32.dll" Alias "ChangeDisplaySettingsA" (lpDevMode As DEVMODE, ByVal dwFalgs As Long) As Long
Public Sub SetVideoMode(Width As Long, height As Long, Depth As Long)
Dim dm As DEVMODE
dm.dmPelsWidth = Width
dm.dmPelsHeight = height
dm.dmBitsPerPel = Depth
dm.dmSize = Len(dm)
dm.dmFields = DM_PELSWIDTH + DM_PELSHEIGHT + DM_BITSPERPEL
ChangeDisplaySettings dm, 0
End Sub
'19. Открытие/закрытие CD-ROM
'#########################
Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, _
ByVal lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
Dim Status As Integer
Status = mciSendString("Set CDAudio Door Open Wait", 0 &, 0 , 0 )
Status = mciSendString("Set CDAudio Door Closed Wait", 0 &, 0 , 0 )
'20. Как из программы открыть веб-страничку
'#########################
Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Public Const SW_SHOW = 5
Public Sub Navigate(frm As Form, ByVal NavTo As String)
Dim hBrowse As Long
hBrowse = ShellExecute(frm.hwnd, "open", NavTo, "", "", SW_SHOW)
End Sub
Navigate Me, "http://vkontakte.ru"
'21. Скрыть/показать кнопку "ПУСК"
'#########################
Option Explicit
Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, _
ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Sub StartButtonState(tState As Boolean)
Dim handle As Long, FindClass As Long, mPopup As Long
FindClass = FindWindow("Shell_TrayWnd", "")
handle = FindWindowEx(FindClass, 0 , "Button", vbNullString)
mPopup = FindWindowEx(handle, 0 , "POPUP", vbNullString)
Select Case tState
Case "True"
ShowWindow handle&, 1
Case "False"
ShowWindow handle&, 0
End Select
End Sub
StartButtonState True 'скрывает "ПУСК"
'22. Скрыть/показать все панель (system tray)
'#########################
Option Explicit
Dim hWnd1 As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, _
ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Const SWP_HIDEWINDOW = &H80
Const SWP_SHOWWINDOW = &H40
Private Sub cmdHide_Click()
'событие скрыть:
hWnd1 = FindWindow("Shell_traywnd", "")
Call SetWindowPos(hWnd1, 0 , 0 , 0 , 0 , 0 , SWP_HIDEWINDOW)
'Это в событие показать:
hWnd1 = FindWindow("Shell_traywnd", "")
Call SetWindowPos(hWnd1, 0 , 0 , 0 , 0 , 0 , SWP_SHOWWINDOW)
'23. Проверить наличие дискеты или CD-диска в устройстве
'#########################
Private Declare Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA" _
(ByVal lpRootPathName As String, ByVal lpVolumeNameBuffer As String, ByVal nVolumeNameSize As Long, _
lpVolumeSerialNumber As Long, lpMaximumComponentLength As Long, lpFileSystemFlags As Long, _
ByVal lpFileSystemNameBuffer As String, ByVal nFileSystemNameSize As Long) As Long
Private Sub Command1_Click()
erg& = GetVolumeInformation("A:", VolName$, 127 &, VolNumber&, MCM&, FSF&, FSys$, 127 &)
If erg& = 0 Then
MsgBox "Ничего в текущем устройстве нет"
Else
MsgBox "В текущем устройстве присутствует диск"
End If
End Sub
'24. Имитация нажатия кнопки на мышке
'#########################
Private Declare Sub mouse_event Lib "user32" _
(ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cbuttons As Long, ByVal dwExtraInfo As Long)
Private Const MOUSEEVENTF_LEFTDOWN = &H2
Private Const MOUSEEVENTF_LEFTUP = &H4
Private Const MOUSEEVENTF_MIDDLEDOWN = &H20
Private Const MOUSEEVENTF_MIDDLEUP = &H40
Private Const MOUSEEVENTF_RIGHTDOWN = &H8
Private Const MOUSEEVENTF_RIGHTUP = &H10
Private Enum ButtonClick
btcLeft
btcRight
btcMiddle
End Enum
Private Function MouseClick(ByVal MBClick As ButtonClick) As Boolean
Dim cbuttons As Long
Dim dwExtraInfo As Long
Dim mevent As Long
Select Case MBClick
Case ButtonLeft
mevent = MOUSEEVENTF_LEFTDOWN Or MOUSEEVENTF_LEFTUP
Case ButtonRight
mevent = MOUSEEVENTF_RIGHTDOWN Or MOUSEEVENTF_RIGHTUP
Case ButtonMiddle
mevent = MOUSEEVENTF_MIDDLEDOWN Or MOUSEEVENTF_MIDDLEUP
Case Else
MouseClick = False
Exit Function
End Select
mouse_event mevent, 0 &, 0 &, cbuttons, dwExtraInfo
MouseClick = True
End Function
Private Sub Command1_Click()
Call MouseClick(ButtonLeft)
End Sub
'25. Установить границы передвижения курсора
'#########################
Private Declare Sub ClipCursor Lib "user32" (lpRect As Any)
Private Declare Sub GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As Rect)
Private Declare Sub ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI)
Private Declare Sub OffsetRect Lib "user32" (lpRect As Rect, ByVal X As Long, ByVal Y As Long)
Private Type Rect
Left As Integer
Top As Integer
Right As Integer
Bottom As Integer
End Type
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Sub Form_Load()
Command1.Caption = "Ограничить передвижение!"
Command2.Caption = "Снять ограничение!"
End Sub
Private Sub Form_Unload(Cancel As Integer)
ClipCursor ByVal 0 &
End Sub
Private Sub Command1_Click()
Dim client As Rect
Dim upperleft As POINTAPI
GetClientRect Me.hwnd, client
upperleft.X = client.Left
upperleft.Y = client.Top
ClientToScreen Me.hwnd, upperleft
OffsetRect client, upperleft.X, upperleft.Y
ClipCursor client
End Sub
Private Sub Command2_Click()
ClipCursor ByVal 0 &
End Sub
'26. Переключение раскладки
'#########################
'Расположите на форме 2 элемента CommandButton.
Private Declare Function LoadKeyboardLayout Lib "user32" Alias "LoadKeyboardLayoutA" _
(ByVal pwszKLID As String, ByVal flags As Long) As Long
Private Const KLF_ACTIVATE = 1
Private Sub Command1_Click()
dKeyboardLayout "00000419", KLF_ACTIVATE
End Sub
Private Sub Command2_Click()
adKeyboardLayout "00000409", KLF_ACTIVATE
End Sub
'27. Какая раскладка клавиатуры включена в данный момент
'#########################
Private Declare Function GetKeyboardLayoutName Lib "user32" Alias "GetKeyboardLayoutNameA" (ByVal pwszKLID As String) As Long
Private Sub Form_Load()
Dim KeybLayoutName As String
KeybLayoutName = String( 9 , 0 )
GetKeyboardLayoutName KeybLayoutName
If CStr(CLng(Left$(KeybLayoutName, InStr( 1 , KeybLayoutName, Chr( 0 )) - 1 ))) = 409 Then MsgBox "Текущая раскладка - Английская"
If CStr(CLng(Left$(KeybLayoutName, InStr( 1 , KeybLayoutName, Chr( 0 )) - 1 ))) = 419 Then MsgBox "Текущая раскладка - Русская"
End Sub
'28. Скорость повтора ввода символов
'#########################
Const SPI_GETKEYBOARDSPEED = 10
Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" _
(ByVal uAction As Long, ByVal uParam As Long, lpvParam As Any, ByVal fuWinIni As Long) As Long
Private Sub Form_Load()
Dim X As Long
Xx = SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0 , X, 0 )
MsgBox "Скорость повтора - " & X & " символов!"
End Sub
'29. Удаление всех файлов из директории
'#########################
Kill ("c:\1\*.*")
'30. Открыть любой файл/директорию
'#########################
'Под Windos NT
Shell "cmd /X /C start c:\mydoc\example.doc"
'Под Windos 9x:
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Private Sub Command1_Click()
ShellExecute 0 , vbNullString, "C:\" & sFile, vbNullString, vbNullString, vbNormalFocus
End Sub
'Или без всяких Апи:
Shell "start c:\mydoc\example.doc"
'31. Функция удаляет только папку, не содержающую файлов !
'#########################
Private Declare Function RemoveDirectory Lib "kernel32.dll" Alias "RemoveDirectoryA" (ByVal lpPathName As String) As Long
Private Sub Command1_Click()
RetVal = RemoveDirectory("D:\ХХХ")
If RetVal = 1 Then
MsgBox "Папка была удалена", vbInformation
Else
MsgBox "Операция провалилась", vbCritical
End If
End
End Sub
'32. Изменение атрибутов файла
'#########################
'Замените "C:\Scan Port.exe" на полный путь к своему файлу.
SetAttr "C:\Scan Port.exe", vbReadOnly 'Поставить атрибут "Только чтение"
SetAttr "C:\Scan Port.exe", GetAttr("C:\Scan Port.exe") And (Not vbReadOnly) 'Очистить атрибут "Только чтение"
SetAttr "C:\Scan Port.exe", vbArchive 'Поставить атрибут "Архивный"
SetAttr "C:\Scan Port.exe", GetAttr("C:\Scan Port.exe") And (Not vbArchive) 'Очистить атрибут "Архивный"
SetAttr "C:\Scan Port.exe", vbHidden 'Поставить атрибут "Скрытый"
SetAttr "C:\Scan Port.exe", GetAttr("C:\Scan Port.exe") And (Not vbHidden) 'Очистить атрибут "Скрытый"
'33. Получение полного пути exe-файла из его хэндла
'#########################
Const TH32CS_SNAPPROCESS As Long = 2 &
Const MAX_PATH As Long = 260
Private Type PROCESSENTRY32
dwSize As Long
cntUsage As Long
th32ProcessID As Long
th32DefaultHeapID As Long
th32ModuleID As Long
cntThreads As Long
th32ParentProcessID As Long
pcPriClassBase As Long
dwFlags As Long
szexeFile As String * MAX_PATH
End Type
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function CreateToolhelpSnapshot Lib "kernel32" Alias "CreateToolhelp32Snapshot" (ByVal lFlgas As Long, ByVal lProcessID As Long) As Long
Private Declare Function ProcessFirst Lib "kernel32" Alias "Process32First" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Function ProcessNext Lib "kernel32" Alias "Process32Next" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Sub CloseHandle Lib "kernel32" (ByVal hPass As Long)
Private Function GetExeFromHandle(hwnd As Long) As String
Dim threadID As Long, processID As Long, hSnapshot As Long
Dim uProcess As PROCESSENTRY32, rProcessFound As Long
Dim i As Integer, szExename As String
threadID = GetWindowThreadProcessId(hwnd, processID)
If threadID = 0 Or processID = 0 Then Exit Function
hSnapshot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS, 0 &)
If hSnapshot = - 1 Then Exit Function
uProcess.dwSize = Len(uProcess)
rProcessFound = ProcessFirst(hSnapshot, uProcess)
Do While rProcessFound
If uProcess.th32ProcessID = processID Then
i = InStr( 1 , uProcess.szexeFile, Chr( 0 ))
If i > 0 Then szExename = Left$(uProcess.szexeFile, i - 1 )
Exit Do
Else
rProcessFound = ProcessNext(hSnapshot, uProcess)
End If
Loop
Call CloseHandle(hSnapshot)
GetExeFromHandle = szExename
End Function
Private Sub Command1_Click()
MsgBox GetExeFromHandle(Me.hwnd)
End Sub
'34. Создание директории
'#########################
Sub MakeDir(dirname As String)
Dim i As Long, path As String
Do
i = InStr(i + 1 , dirname & "\", "\")
path = Left$(dirname, i - 1 )
If Right$(path, 1 ) <> ":" And Dir$(path, vbDirectory) = "" Then
MkDir path
End If
Loop Until i >= Len(dirname)
End Sub
Private Sub Command1_Click()
Call MakeDir("C:\X\YYY\AAA\BBB\")
End Sub
' '35. 'Сохранение файла из Интернета
''#########################
'
'Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
'Public Event ErrorDownload (FromPathName As String, ToPathName As String)
'Public Event DownloadComplete(FromPathName As String, ToPathName As String)
'
'Public Function DownloadFile(FromPathName As String, ToPathName As String)
' If URLDownloadToFile(0, FromPathName, ToPathName, 0, 0) = 0 Then
' DownloadFile = True
' RaiseEvent DownloadComplete(FromPathName, ToPathName)
' Else
' DownloadFile = False
' RaiseEvent ErrorDownload(FromPathName, ToPathName)
' End If
'End Function
'
'Private Sub Command1_Click()
'Call DownloadFile("http://visual-basic.nm.ru/Banner.gif", "c:\Banner.gif")
'End Sub
'36. Получить имя компьютера и имя пользователя
'#########################
Private Declare Function GetComputerNameA Lib "kernel32" (ByVal lpBuffer As String, nSize As Long) As Long
Private Declare Function WNetGetUserA Lib "mpr.dll" (ByVal lpName As String, ByVal lpUsername As String, lpnLength As Long) As Long
Function GetComputerName() As String
Dim sBuffer As String * 255
If GetComputerNameA(sBuffer, 255 &) <> 0 Then
GetComputerName = Left$(sBuffer, InStr(sBuffer, vbNullChar) - 1 )
End If
End Function
Function GetUserName() As String
Dim sUserNameBuff As String * 255
sUserNameBuff = Space( 255 )
Call WNetGetUserA(vbNullString, sUserNameBuff, 255 &)
GetUserName = Left$(sUserNameBuff, InStr(sUserNameBuff, vbNullChar) - 1 )
End Function
'37. Изменить разрешение экрана
'#########################
'Ваш монитор должен поддерживать задаваемое разрешение !
Private Declare Function ChangeDisplaySettings Lib "user32" Alias _
"ChangeDisplaySettingsA" (lpDevMode As Any, ByVal dwFlags As Long) As Long
Private Declare Function EnumDisplaySettings Lib "user32" Alias _
"EnumDisplaySettingsA" (ByVal lpszDeviceName As Long, ByVal iModeNum As _
Long, lpDevMode As Any) As Boolean
Const DM_PELSWIDTH = &H80000
Const DM_PELSHEIGHT = &H100000
Const CCFORMNAME = 32
Const CCDEVICENAME = 32
Private Type DEVMODE
dmDeviceName As String * CCDEVICENAME
dmSpecVersion As Integer
dmDriverVersion As Integer
dmSize As Integer
dmDriverExtra As Integer
dmFields As Long
dmOrientation As Integer
dmPaperSize As Integer
dmPaperLength As Integer
dmPaperWidth As Integer
dmScale As Integer
dmCopies As Integer
dmDefaultSource As Integer
dmPrintQuality As Integer
dmColor As Integer
dmDuplex As Integer
dmYResolution As Integer
dmTTOption As Integer
dmCollate As Integer
dmFormName As String * CCFORMNAME
dmUnusedPadding As Integer
dmBitsPerPel As Integer
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
End Type
Private Sub ChangeResolution(iWidth As Single, iHeight As Single)
Dim DevM As DEVMODE
Dim A As Boolean
Dim i As Long
Dim b As Long
i = 0
Do
A = EnumDisplaySettings( 0 &, i&, DevM)
i = i + 1
Loop Until (A = False)
DevM.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT
DevM.dmPelsWidth = iWidth
DevM.dmPelsHeight = iHeight
b = ChangeDisplaySettings(DevM, 0 )
End Sub
Private Sub Command1_Click()
ChangeResolution 640 , 480
End Sub
'38. Получить IP адрес
'#########################
'Вставьте следующий код в событие формы
Private Sub Form_Load()
MsgBox "IP Host Name: " & GetIPHostName()
MsgBox "IP Address: " & GetIPAddress()
End Sub
'Добавьте модуль в проект
Public Const MAX_WSADescription = 256
Public Const MAX_WSASYSStatus = 128
Public Const ERROR_SUCCESS As Long = 0
Public Const WS_VERSION_REQD As Long = &H101
Public Const WS_VERSION_MAJOR As Long = WS_VERSION_REQD \ &H100 And &HFF&
Public Const WS_VERSION_MINOR As Long = WS_VERSION_REQD And &HFF&
Public Const MIN_SOCKETS_REQD As Long = 1
Public Const SOCKET_ERROR As Long = - 1
Public Type HOSTENT
hName As Long
hAliases As Long
hAddrType As Integer
hLen As Integer
hAddrList As Long
End Type
Public Type WSAData
wVersion As Integer
wHighVersion As Integer
szDescription( 0 To MAX_WSADescription) As Byte
szSystemStatus( 0 To MAX_WSASYSStatus) As Byte
wMaxSockets As Integer
wMaxUDPDG As Integer
dwVendorInfo As Long
End Type
Public Declare Function WSAGetLastError Lib "wsock32.dll" () As Long
Public Declare Function WSAStartup Lib "wsock32.dll" (ByVal _
wVersionRequired As Long, lpWSADATA As WSAData) As Long
Public Declare Function WSACleanUp Lib "wsock32.dll" Alias "WSACleanup" () As Long
Public Declare Function GetHostName Lib "wsock32.dll" Alias "gethostname" (ByVal _
szHost As String, ByVal dwHostLen As Long) As Long
Public Declare Function gethostbyname Lib "wsock32.dll" (ByVal szHost As _
String) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(hpvDest As Any, ByVal hpvSource As Long, ByVal cbCopy As Long)
Public Function GetIPAddress() As String
Dim sHostName As String * 256
Dim lpHost As Long
Dim Host As HOSTENT
Dim dwIPAddr As Long
Dim tmpIPAddr() As Byte
Dim i As Integer
Dim sIPAddr As String
If Not SocketsInitialize() Then
GetIPAddress = ""
Exit Function
End If
If GetHostName(sHostName, 256 ) = SOCKET_ERROR Then
GetIPAddress = ""
MsgBox "Windows Sockets error " & Str$(WSAGetLastError()) & " has occurred. Unable to successfully get Host Name."
SocketsCleanup
Exit Function
End If
sHostName = Trim$(sHostName)
lpHost = gethostbyname(sHostName)
If lpHost = 0 Then
GetIPAddress = ""
MsgBox "Windows Sockets are not responding. " & "Unable to successfully get Host Name."
SocketsCleanup
Exit Function
End If
CopyMemory Host, lpHost, Len(Host)
CopyMemory dwIPAddr, Host.hAddrList, 4
ReDim tmpIPAddr( 1 To Host.hLen)
CopyMemory tmpIPAddr( 1 ), dwIPAddr, Host.hLen
For i = 1 To Host.hLen
sIPAddr = sIPAddr & tmpIPAddr(i) & "."
Next
GetIPAddress = Mid$(sIPAddr, 1 , Len(sIPAddr) - 1 )
SocketsCleanup
End Function
Public Function GetIPHostName() As String
Dim sHostName As String * 256
If Not SocketsInitialize() Then
GetIPHostName = ""
Exit Function
End If
If GetHostName(sHostName, 256 ) = SOCKET_ERROR Then
GetIPHostName = ""
MsgBox "Windows Sockets error " & Str$(WSAGetLastError()) & " has occurred. Unable to successfully get Host Name."
SocketsCleanup
Exit Function
End If
GetIPHostName = Left$(sHostName, InStr(sHostName, Chr( 0 )) - 1 )
SocketsCleanup
End Function
Public Function HiByte(ByVal wParam As Integer)
HiByte = wParam \ &H100 And &HFF&
End Function
Public Function LoByte(ByVal wParam As Integer)
LoByte = wParam And &HFF&
End Function
Public Sub SocketsCleanup()
If WSACleanUp() <> ERROR_SUCCESS Then
MsgBox "Socket error occurred in Cleanup."
End If
End Sub
Public Function SocketsInitialize() As Boolean
Dim WSAD As WSAData
Dim sLoByte As String
Dim sHiByte As String
If WSAStartup(WS_VERSION_REQD, WSAD) <> ERROR_SUCCESS Then
MsgBox "The 32-bit Windows Socket is not responding."
SocketsInitialize = False
Exit Function
End If
If WSAD.wMaxSockets < MIN_SOCKETS_REQD Then
MsgBox "This application requires a minimum of " & CStr(MIN_SOCKETS_REQD) & " supported sockets."
SocketsInitialize = False
Exit Function
End If
If LoByte(WSAD.wVersion) < WS_VERSION_MAJOR Or (LoByte(WSAD.wVersion) = WS_VERSION_MAJOR And HiByte(WSAD.wVersion) < WS_VERSION_MINOR) Then
sHiByte = CStr(HiByte(WSAD.wVersion))
sLoByte = CStr(LoByte(WSAD.wVersion))
MsgBox "Sockets version " & sLoByte & "." & sHiByte & " is not supported by 32-bit Windows Sockets."
SocketsInitialize = False
Exit Function
End If
SocketsInitialize = True
End Function
'39. Определение имени или IP-адреса удаленного компьютера
'#########################
'Добавьте модуль, и CommandButton.
'КОД ФОРМЫ
Private Sub Command1_Click()
'Вначале вы должны инициализировать winsock
WinsockInit
'Определение имени машины, зная ее IP-адрес
MsgBox HostByAddress("192.168.1.1")
MsgBox HostByAddress("192.168.1.2")
'Определение IP-адреса машины, зная ее имя
MsgBox HostByName("GARIK")
MsgBox HostByName("OKSANA")
'В конце работы вы должны использовать функцию WSACleanUp
WSACleanUp
End Sub
'КОД МОДУЛЯ
Option Explicit
Public Const SOCKET_ERROR = - 1
Public Const AF_INET = 2
Public Const PF_INET = AF_INET
Public Const MAXGETHOSTSTRUCT = 1024
Public Const SOCK_STREAM = 1
Public Const MSG_PEEK = 2
Private Type SockAddr
sin_family As Integer
sin_port As Integer
sin_addr As String * 4
sin_zero As String * 8
End Type
Private Type T_WSA
wVersion As Integer
wHighVersion As Integer
szDescription( 0 To 255 ) As Byte
szSystemStatus( 0 To 128 ) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpVendorInfo As Long
End Type
Dim WSAData As T_WSA
Type Inet_Address
Byte4 As String * 1
Byte3 As String * 1
Byte2 As String * 1
Byte1 As String * 1
End Type
Public IPStruct As Inet_Address
Public Type T_Host
h_name As Long
h_aliases As Long
h_addrtype As Integer
h_length As Integer
h_addr_list As Long
End Type
Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Dest As _
Any, Src As Any, ByVal cb&)
Declare Function gethostbyaddr Lib "wsock32.dll" (addr As Long, ByVal _
addr_len As Long, ByVal addr_type As Long) As Long
Declare Function inet_addr Lib "wsock32.dll" (ByVal addr As String) As _
Long
Declare Function gethostbyname Lib "wsock32.dll" _
(ByVal HostName As String) As Long
Declare Function GetHostName Lib "wsock32.dll" Alias "gethostname" (ByVal _
HostName As String, HostLen As Long) As Long
Declare Function WSAStartup Lib "wsock32.dll" (ByVal A As Long, b As _
T_WSA) As Long
Declare Function WSACleanUp Lib "wsock32.dll" Alias "WSACleanup" () As _
Integer
Function HostByName(sHost As String) As String
Dim s As String
Dim p As Long
Dim Host As T_Host
Dim ListAddress As Long
Dim ListAddr As Long
Dim Address As Long
s = String( 64 , 0 )
sHost = sHost + Right(s, 64 - Len(sHost))
p = gethostbyname(sHost)
If p = SOCKET_ERROR Then
Exit Function
Else
If p <> 0 Then
CopyMemory Host.h_name, ByVal p, Len(Host)
ListAddress = Host.h_addr_list
CopyMemory ListAddr, ByVal ListAddress, 4
CopyMemory Address, ByVal ListAddr, 4
HostByName = InetAddrLongToString(Address)
Else
HostByName = "No DNS Entry"
End If
End If
End Function
Private Function InetAddrLongToString(Address As Long) As String
CopyMemory IPStruct, Address, 4
InetAddrLongToString = CStr(Asc(IPStruct.Byte4)) + "." + _
CStr(Asc(IPStruct.Byte3)) + "." + CStr(Asc(IPStruct.Byte2)) + "." + _
CStr(Asc(IPStruct.Byte1))
End Function
Function HostByAddress(ByVal sAddress As String) As String
Dim lAddress As Long
Dim p As Long
Dim HostName As String
Dim Host As T_Host
lAddress = inet_addr(sAddress)
p = gethostbyaddr(lAddress, 4 , PF_INET)
If p <> 0 Then
CopyMemory Host, ByVal p, Len(Host)
HostName = String( 256 , 0 )
CopyMemory ByVal HostName, ByVal Host.h_name, 256
If HostName = "" Then HostByAddress = "Unable to Resolve Address"
HostByAddress = Left(HostName, InStr(HostName, Chr( 0 )) - 1 )
Else
HostByAddress = "No DNS Entry"
End If
End Function
Public Sub WinsockInit()
WSAStartup &H101, WSAData
End Sub
'40. Программно отсоединиться от Интернета
'#########################
'Добавьте на форму CommandButton
Const RAS_MAXENTRYNAME As Integer = 256
Const RAS_MAXDEVICETYPE As Integer = 16
Const RAS_MAXDEVICENAME As Integer = 128
Const RAS_RASCONNSIZE As Integer = 412
Const ERROR_SUCCESS = 0 &
Private Type RasEntryName
dwSize As Long
szEntryName(RAS_MAXENTRYNAME) As Byte
End Type
Private Type RasConn
dwSize As Long
hRasConn As Long
szEntryName(RAS_MAXENTRYNAME) As Byte
szDeviceType(RAS_MAXDEVICETYPE) As Byte
szDeviceName(RAS_MAXDEVICENAME) As Byte
End Type
Private Declare Function RasEnumConnections Lib "RasApi32.dll" Alias _
"RasEnumConnectionsA" (lpRasConn As Any, lpcb As Long, lpcConnections As Long) As Long
Private Declare Function RasHangUp Lib "RasApi32.dll" Alias "RasHangUpA" _
(ByVal hRasConn As Long) As Long
Private gstrISPName As String
Public ReturnCode As Long
Public Sub HangUp()
Dim i As Long
Dim lpRasConn( 255 ) As RasConn
Dim lpcb As Long
Dim lpcConnections As Long
Dim hRasConn As Long
lpRasConn( 0 ).dwSize = RAS_RASCONNSIZE
lpcb = RAS_MAXENTRYNAME * lpRasConn( 0 ).dwSize
lpcConnections = 0
ReturnCode = RasEnumConnections(lpRasConn( 0 ), lpcb, lpcConnections)
If ReturnCode = ERROR_SUCCESS Then
For i = 0 To lpcConnections - 1
If Trim(ByteToString(lpRasConn(i).szEntryName)) = Trim(gstrISPName) Then
hRasConn = lpRasConn(i).hRasConn
ReturnCode = RasHangUp(ByVal hRasConn)
End If
Next i
End If
End Sub
Public Function ByteToString(bytString() As Byte) As String
Dim i As Integer
ByteToString = ""
i = 0
While bytString(i) = 0 &
ByteToString = ByteToString & Chr(bytString(i))
i = i + 1
Wend
End Function
Private Sub Command1_Click()
Call HangUp
End Sub
'41. Узнать есть ли активное соединение с Интернетом
'#########################
Private Declare Function RasEnumConnections Lib "RasApi32.dll" Alias _
"RasEnumConnectionsA" (lpRasCon As Any, lpcb As Long, lpcConnections As Long) As Long
Private Declare Function RasGetConnectStatus Lib "RasApi32.dll" Alias _
"RasGetConnectStatusA" (ByVal hRasCon As Long, lpStatus As Any) As Long
Private Const RAS95_MaxEntryName = 256
Private Const RAS95_MaxDeviceType = 16
Private Const RAS95_MaxDeviceName = 32
Private Type RASCONN95
dwSize As Long
hRasCon As Long
szEntryName(RAS95_MaxEntryName) As Byte
szDeviceType(RAS95_MaxDeviceType) As Byte
szDeviceName(RAS95_MaxDeviceName) As Byte
End Type
Private Type RASCONNSTATUS95
dwSize As Long
RasConnState As Long
dwError As Long
szDeviceType(RAS95_MaxDeviceType) As Byte
szDeviceName(RAS95_MaxDeviceName) As Byte
End Type
Public Function IsConnected() As Boolean
Dim TRasCon( 255 ) As RASCONN95
Dim lg As Long
Dim lpcon As Long
Dim RetVal As Long
Dim Tstatus As RASCONNSTATUS95
TRasCon( 0 ).dwSize = 412
lg = 256 * TRasCon( 0 ).dwSize
RetVal = RasEnumConnections(TRasCon( 0 ), lg, lpcon)
Tstatus.dwSize = 160
RetVal = RasGetConnectStatus(TRasCon( 0 ).hRasCon, Tstatus)
If Tstatus.RasConnState = &H2000 Then
IsConnected = True
Else
IsConnected = False
End If
End Function
Private Sub Form_Load()
'если есть соединение, то IsConnected() = True, иначе False
MsgBox IsConnected()
End Sub
'42. Вызвать окно "Установка связи с Интернетом"
'#########################
Private Sub Form_Load()
ult = Shell("rundll32.exe rnaui.DLL,RnaDial", 1 )
End Sub
'43. Симулировать нажатия определенных клавиш
'#########################
Private Declare Sub keybd_event Lib "user32" _
(ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
'bVk - Виртуальный код клавиши для имитации нажатия и отпускания клавиши.
'bScan - Зарезервировано -- установлено в 0.
'dwFlags - Комбинация следующих флагов определяет различные способы имитации:
'KEYEVENTF_EXTENDEDKEY - Префикс скэн-кода с префиксным байтом, имеющим значение &HE0.
'KEYEVENTF_KEYUP - Клавиша, указанная в bVk будет отпущена. Если этот флажок не определен, клавиша будет нажата.
'dwExtraInfo - Дополнительное 32-разрядное значение, связанное с событием клавиатуры.
Const KEYEVENTF_KEYUP = &H2 'событие отпускания клавиши
Const VK_CONTROL = &H11 'клавиша Ctrl
Const VK_ESCAPE = &H1B 'клавиша Escape
'Эмулирующая нажатие кнопки ПУСК
Private Sub ShowStartMenu()
'Функция эмулирует нажатие Ctrl + Esc
Call keybd_event(VK_CONTROL, 0 , 0 , 0 ) 'Hажимаем Ctrl
Call keybd_event(VK_ESCAPE, 0 , 0 , 0 ) 'Hажимаем Esc
Call keybd_event(VK_ESCAPE, 0 , KEYEVENTF_KEYUP, 0 ) 'Отпускаем Esc
Call keybd_event(VK_CONTROL, 0 , KEYEVENTF_KEYUP, 0 ) 'Отпускаем Ctrl
End Sub
Private Sub Command1_Click()
ShowStartMenu
End Sub
'эмуляция нажатия клавиши Alt
Call keybd_event(VK_ADD, 0 , 0 , 0 )
Call keybd_event(VK_ADD, 0 , KEYEVENTF_KEYUP, 0 )
'эмуляция нажатия левой кнопки с логотипом Windows
Call keybd_event(VK_LWIN, 0 , 0 , 0 )
Call keybd_event(VK_LWIN, 0 , KEYEVENTF_KEYUP, 0 )
'Запустить проводник
Call keybd_event(VK_LWIN, 0 , 0 , 0 )
Call keybd_event( 69 , 0 , 0 , 0 )
Call keybd_event(VK_LWIN, 0 , KEYEVENTF_KEYUP, 0 )
'поиск файла
'Call keybd_event(VK_LWIN, 0, 0, 0)
'Call keybd_event(70, 0, 0, 0)
'Call keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0)
Private Const VK_ADD = &H6B
Private Const VK_ATTN = &HF6
Private Const VK_BACK = &H8
Private Const VK_CANCEL = &H3
Private Const VK_CAPITAL = &H14
Private Const VK_CLEAR = &HC
Private Const VK_CONTROL = &H11
Private Const VK_CRSEL = &HF7
Private Const VK_DECIMAL = &H6E
Private Const VK_DELETE = &H2E
Private Const VK_DIVIDE = &H6F
Private Const VK_DOWN = &H28
Private Const VK_END = &H23
Private Const VK_EREOF = &HF9
Private Const VK_ESCAPE = &H1B
Private Const VK_EXECUTE = &H2B
Private Const VK_EXSEL = &HF8
Private Const VK_F1 = &H70
Private Const VK_F10 = &H79
Private Const VK_F11 = &H7A
Private Const VK_F12 = &H7B
Private Const VK_F13 = &H7C
Private Const VK_F14 = &H7D
Private Const VK_F15 = &H7E
Private Const VK_F16 = &H7F
Private Const VK_F17 = &H80
Private Const VK_F18 = &H81
Private Const VK_F19 = &H82
Private Const VK_F2 = &H71
Private Const VK_F20 = &H83
Private Const VK_F21 = &H84
Private Const VK_F22 = &H85
Private Const VK_F23 = &H86
Private Const VK_F24 = &H87
Private Const VK_F3 = &H72
Private Const VK_F4 = &H73
Private Const VK_F5 = &H74
Private Const VK_F6 = &H75
Private Const VK_F7 = &H76
Private Const VK_F8 = &H77
Private Const VK_F9 = &H78
Private Const VK_HELP = &H2F
Private Const VK_HOME = &H24
Private Const VK_INSERT = &H2D
Private Const VK_LBUTTON = &H1
Private Const VK_LCONTROL = &HA2
Private Const VK_LEFT = &H25
Private Const VK_LMENU = &HA4
Private Const VK_LSHIFT = &HA0
Private Const VK_MBUTTON = &H4
Private Const VK_MENU = &H12
Private Const VK_MULTIPLY = &H6A
Private Const VK_NEXT = &H22
Private Const VK_NONAME = &HFC
Private Const VK_NUMLOCK = &H90
Private Const VK_NUMPAD0 = &H60
Private Const VK_NUMPAD1 = &H61
Private Const VK_NUMPAD2 = &H62
Private Const VK_NUMPAD3 = &H63
Private Const VK_NUMPAD4 = &H64
Private Const VK_NUMPAD5 = &H65
Private Const VK_NUMPAD6 = &H66
Private Const VK_NUMPAD7 = &H67
Private Const VK_NUMPAD8 = &H68
Private Const VK_NUMPAD9 = &H69
Private Const VK_OEM_CLEAR = &HFE
Private Const VK_PA1 = &HFD
Private Const VK_PAUSE = &H13
Private Const VK_PLAY = &HFA
Private Const VK_PRINT = &H2A
Private Const VK_PRIOR = &H21
Private Const VK_PROCESSKEY = &HE5
Private Const VK_RBUTTON = &H2
Private Const VK_RCONTROL = &HA3
Private Const VK_RETURN = &HD
Private Const VK_RIGHT = &H27
Private Const VK_RMENU = &HA5
Private Const VK_RSHIFT = &HA1
Private Const VK_SCROLL = &H91
Private Const VK_SELECT = &H29
Private Const VK_SEPARATOR = &H6C
Private Const VK_SHIFT = &H10
Private Const VK_SNAPSHOT = &H2C
Private Const VK_SPACE = &H20
Private Const VK_SUBTRACT = &H6D
Private Const VK_TAB = &H9
Private Const VK_UP = &H26
Private Const VK_ZOOM = &HFB
'44. Подключение, отключение сетевого диска
'#########################
'Добавьте дополнительный модуль, и 2 элемента CommandButton.
'КОД ФОРМЫ
Private Sub Command1_Click()
Call Module1.Connect("Sany\c$", "K:", "defaultsharename", "garik")
If (Module1.rc <> 0 ) And (Module1.rc <> 85 ) Then
MsgBox Module1.ErrorMsg
End If
End Sub
Private Sub Command2_Click()
Call Module1.DisConnect("K:", True)
If (Module1.rc <> 0 ) And (Module1.rc <> 85 ) Then
MsgBox Module1.ErrorMsg
End If
End Sub
'КОД МОДУЛЯ
Option Explicit
Public Declare Function WNetAddConnection2 Lib "mpr.dll" Alias "WNetAddConnection2A" (lpNetResource As NETRESOURCE, ByVal lpPassword As String, ByVal lpUsername As String, ByVal dwFlags As Long) As Long
Public Declare Function WNetCancelConnection2 Lib "mpr.dll" Alias "WNetCancelConnection2A" (ByVal lpName As String, ByVal dwFlags As Long, ByVal fForce As Long) As Long
Public ErrorNum As Long
Public ErrorMsg As String
Public rc As Long
Public RemoteName As String
Public Const ERROR_BAD_DEV_TYPE = 66 &
Public Const ERROR_ALREADY_ASSIGNED = 85 &
Public Const ERROR_ACCESS_DENIED = 5 &
Public Const ERROR_BAD_NET_NAME = 67 &
Public Const ERROR_BAD_PROFILE = 1206 &
Public Const ERROR_BAD_PROVIDER = 1204 &
Public Const ERROR_BUSY = 170 &
Public Const ERROR_CANCEL_VIOLATION = 173 &
Public Const ERROR_CANNOT_OPEN_PROFILE = 1205 &
Public Const ERROR_DEVICE_ALREADY_REMEMBERED = 1202 &
Public Const ERROR_EXTENDED_ERROR = 1208 &
Public Const ERROR_INVALID_PASSWORD = 86 &
Public Const ERROR_NO_NET_OR_BAD_PATH = 1203 &
Public Const ERROR_NO_NETWORK = 1222 &
Public Const ERROR_NO_CONNECTION = 8
Public Const ERROR_NO_DISCONNECT = 9
Public Const ERROR_DEVICE_IN_USE = 2404 &
Public Const ERROR_NOT_CONNECTED = 2250 &
Public Const ERROR_OPEN_FILES = 2401 &
Public Const ERROR_MORE_DATA = 234
Public Const CONNECT_UPDATE_PROFILE = &H1
Public Const RESOURCETYPE_DISK = &H1
Public Type NETRESOURCE
dwScope As Long
dwType As Long
dwDisplayType As Long
dwUsage As Long
lpLocalName As String
lpRemoteName As String
lpComment As String
lpProvider As String
End Type
Public lpNetResourse As NETRESOURCE
Public Sub Connect(ByVal HostName As String, ByVal RemoteName As String, ByVal Username As String, ByVal Password As String)
Dim lpUsername As String
Dim lpPassword As String
On Error GoTo Err_Connect
ErrorNum = 0
ErrorMsg = ""
lpNetResourse.dwType = RESOURCETYPE_DISK
lpNetResourse.lpLocalName = RemoteName & Chr( 0 )
'Drive Letter to use
lpNetResourse.lpRemoteName = "\\" & HostName & Chr( 0 )
'Network Path to share
lpNetResourse.lpProvider = Chr( 0 )
lpPassword = Password & Chr( 0 )
'password on share pass "" if none
lpUsername = Username & Chr( 0 )
'username to connect as if applicable
rc = WNetAddConnection2(lpNetResourse, lpPassword, lpUsername, CONNECT_UPDATE_PROFILE)
If rc <> 0 Then GoTo Err_Connect
Exit Sub
Err_Connect:
ErrorNum = rc
ErrorMsg = WnetError(rc)
End Sub
Public Sub DisConnect(ByVal name As String, ByVal ForceOff As Boolean)
On Error GoTo Err_DisConnect
ErrorNum = 0
ErrorMsg = ""
rc = WNetCancelConnection2(name & Chr( 0 ), CONNECT_UPDATE_PROFILE, ForceOff)
If rc <> 0 Then GoTo Err_DisConnect
Exit Sub
Err_DisConnect:
ErrorNum = rc
ErrorMsg = WnetError(rc)
End Sub
Private Function WnetError(Errcode As Long) As String
Select Case Errcode
Case ERROR_BAD_DEV_TYPE
WnetError = "Bad device."
Case ERROR_ALREADY_ASSIGNED
WnetError = "Already Assigned."
Case ERROR_ACCESS_DENIED
WnetError = "Access Denied."
Case ERROR_BAD_NET_NAME
WnetError = "Bad net name"
Case ERROR_BAD_PROFILE
WnetError = "Bad Profile"
Case ERROR_BAD_PROVIDER
WnetError = "Bad Provider"
Case ERROR_BUSY
WnetError = "Busy"
Case ERROR_CANCEL_VIOLATION
WnetError = "Cancel Violation"
Case ERROR_CANNOT_OPEN_PROFILE
WnetError = "Cannot Open Profile"
Case ERROR_DEVICE_ALREADY_REMEMBERED
WnetError = "Device already remembered"
Case ERROR_EXTENDED_ERROR
WnetError = "Device already remembered"
Case ERROR_INVALID_PASSWORD
WnetError = "Invalid Password"
Case ERROR_NO_NET_OR_BAD_PATH
WnetError = "Could not find the specified device"
Case ERROR_NO_NETWORK
WnetError = "No Network Present"
Case ERROR_DEVICE_IN_USE
WnetError = "Connection Currently in use "
Case ERROR_NOT_CONNECTED
WnetError = "No Connection Present"
Case ERROR_OPEN_FILES
WnetError = "Files open and the force parameter is false"
Case ERROR_MORE_DATA
WnetError = "Buffer to small to hold network name, make lpnLength bigger"
Case Else:
WnetError = "Unrecognized Error " + Str(Errcode) + "."
End Select
End Function
'45. Установление анимированного курсора
'#########################
Private Declare Function LoadCursorFromFile Lib "user32" Alias "LoadCursorFromFileA" (ByVal lpFileName As String) As Long
Private Declare Function SetClassLong Lib "user32" Alias "SetClassLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Const GCL_HCURSOR = (- 12 )
Dim sCursorFile As String
Dim hCursor As Long
Dim hOldCursor As Long
Dim lReturn As Long
Private Sub Command1_Click()
hCursor = LoadCursorFromFile(sCursorFile)
hOldCursor = SetClassLong(Form1.hwnd, GCL_HCURSOR, hCursor)
End Sub
Private Sub Command2_Click()
lReturn = SetClassLong(Form1.hwnd, GCL_HCURSOR, hOldCursor)
End Sub
Private Sub Form_Load()
'не забудьте указать свой путь к анимированному курсору
sCursorFile = "C:\WIN\CURSORS\GLOBE.ANI"
End Sub
'46. Загрузка разных курсоров
'#########################
' Константы из API интерфейса
Const IDC_ARROW = 32512 & 'Стрелка
Const IDC_IBEAM = 32513 & 'Тип - I
Const IDC_WAIT = 32514 & 'Часы
Const IDC_CROSS = 32515 & 'Перекрестие
Const IDC_UPARROW = 32516 & 'Верх
Const IDC_SIZE = 32640 & 'Размер
Const IDC_ICON = 32641 &
Const IDC_SIZENWSE = 32642 & 'Стрелки размеров
Const IDC_SIZENESW = 32643 &
Const IDC_SIZEWE = 32644 &
Const IDC_SIZENS = 32645 &
Const IDC_SIZEALL = 32646 &
Const IDC_NO = 32648 & 'Стоп курсор
Const IDC_APPSTARTING = 32650 & 'Стрелка и часы
Const IDC_HAND = 32649 &
' Загружает курсор из ресурса
Private Declare Function apiLoadCursorBynum Lib "user32" Alias "LoadCursorA" _
(ByVal hInstance As Long, _
ByVal lpCursorName As Long) _
As Long
' Устанавливает курсор
Private Declare Function apiSetCursor Lib "user32" Alias "SetCursor" _
(ByVal hCursor As Long) _
As Long
' Загружает курсор из файла
Private Declare Function apiLoadCursorFromFile Lib "user32" Alias "LoadCursorFromFileA" _
(ByVal lpFileName As String) _
As Long
'Указатель на курсор
Dim hCursor As Long
' Загружаем курсор
Private Sub Объекты_AfterUpdate()
On Error GoTo 999
Select Case Me.Объекты
Case 1 : 'Указатель
hCursor = apiLoadCursorBynum( 0 , IDC_ARROW)
Case 2 : 'Редактор
hCursor = apiLoadCursorBynum( 0 , IDC_IBEAM)
Case 3 : 'Часы
hCursor = apiLoadCursorBynum( 0 , IDC_WAIT)
Case 4 'Перекрестие
hCursor = apiLoadCursorBynum( 0 , IDC_CROSS)
Case 5 : 'Стрелка вверх
hCursor = apiLoadCursorBynum( 0 , IDC_UPARROW)
Case 6 : 'Размер
hCursor = apiLoadCursorBynum( 0 , IDC_SIZE)
Case 7 : 'Иконка
hCursor = apiLoadCursorBynum( 0 , IDC_ICON)
Case 8 : 'Стрелка
hCursor = apiLoadCursorBynum( 0 , IDC_SIZENWSE)
Case 9 'Стрелка
hCursor = apiLoadCursorBynum( 0 , IDC_SIZENESW)
Case 10 'Стрелка
hCursor = apiLoadCursorBynum( 0 , IDC_SIZEWE)
Case 11 'Стрелка
hCursor = apiLoadCursorBynum( 0 , IDC_SIZENS)
Case 12 'Стрелка
hCursor = apiLoadCursorBynum( 0 , IDC_SIZEALL)
Case 13 'Стоп курсор
hCursor = apiLoadCursorBynum( 0 , IDC_NO)
Case 14 'Старт приложения
hCursor = apiLoadCursorBynum( 0 , IDC_APPSTARTING)
Case 15 'Загрузить из файла
hCursor = apiLoadCursorFromFile( _
Application.CurrentProject.path & _
"\la_api.cur")
Case 16 'Рука курсор
hCursor = apiLoadCursorBynum( 0 , IDC_HAND)
End Select
Exit Sub
999 :
MsgBox Err.Description 'Ошибка
Err.Clear
End Sub
' Изменяем курсор
Private Sub Пример_01_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Call apiSetCursor(hCursor)
End Sub
'47. Отображение/скрытие окна приложения
'#########################
' Константы отображения
Private Const SW_HIDE = 0
Private Const SW_SHOWNORMAL = 1
Private Const SW_NORMAL = 1
Private Const SW_SHOWMINIMIZED = 2
Private Const SW_SHOWMAXIMIZED = 3
Private Const SW_MAXIMIZE = 3
Private Const SW_SHOWNOACTIVATE = 4
Private Const SW_SHOW = 5
Private Const SW_MINIMIZE = 6
Private Const SW_SHOWMINNOACTIVE = 7
Private Const SW_SHOWNA = 8
Private Const SW_RESTORE = 9
Private Const SW_SHOWDEFAULT = 10
Private Const SW_MAX = 10
' Функция управляет отображением окна
Private Declare Function apiShowWindow Lib "user32" Alias "ShowWindow" _
(ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long
' Команды в котором создаются приложения
Dim appAcc As Access.Application
' Отобразить окно
Private Sub butON_Click()
Dim s As String
On Error Resume Next
' Выход из приложения
Form_Close
' Открываем окно
Set appAcc = New Access.Application
s = Application.CurrentProject.path & "\" & "la_form.mdb"
appAcc.OpenCurrentDatabase (s)
appAcc.Visible = True
apiShowWindow appAcc.hWndAccessApp, Me.grShow
End Sub
' Окно базы данных
Private Sub butWinDataBase_Click()
DoCmd.SelectObject acForm, "Пример 05", True
If Me.butWinDataBase = False Then
DoCmd.RunCommand acCmdWindowHide
End If
DoCmd.SelectObject acForm, "Пример 05", False
End Sub
' Выход из системы
Private Sub Form_Close()
On Error Resume Next
appAcc.Quit acQuitSaveNone
Err.Clear
End Sub
'48. Общая информация о Windows
'#########################
' Структура с информацией о версии Windows
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
' Api константы платформы Windows
Const VER_PLATFORM_WIN32s = 0
Const VER_PLATFORM_WIN32_WINDOWS = 1
Const VER_PLATFORM_WIN32_NT = 2
' Получаем информацию о версии
Private Declare Function apiGetVersionEx Lib "kernel32" Alias "GetVersionExA" _
(lpVersionInformation As OSVERSIONINFO) As Long
' Загрузка данных
Private Sub Form_Load()
Dim myVer As OSVERSIONINFO
Dim s As String
' Инициализируем строку
s = ""
' Определяем размер структуры
myVer.dwOSVersionInfoSize = 148
' Получаем информацию о версии
Call apiGetVersionEx(myVer)
If myVer.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS Then
s = s & "Платформа: Windows 95;"
ElseIf myVer.dwPlatformId = VER_PLATFORM_WIN32_NT Then
s = s & "Платформа: Windows NT;"
End If
s = s & "Версия: " & myVer.dwMajorVersion & "." & myVer.dwMinorVersion & ";"
s = s & "Построение: " & (myVer.dwBuildNumber And &HFFFF&) & ";"
' Устанавливаем список
Me.myList.RowSource = s
End Sub
'50. Использование функции timeGetTime
'#########################
' Функция времени в миллисекундах с момента запуска Windows
Private Declare Function apiTimeGetTime Lib "winmm.dll" Alias "timeGetTime" () As Long
Dim T0 As Long, T1 As Long
Private Sub Form_Open(Cancel As Integer)
' Устанавливаем начальное значение
T0 = apiTimeGetTime()
' Определяем список
Me.myList.RowSource = Me.myList.RowSource & ";Form_Open: " & ";" & T0 & ";" & 0
End Sub
Private Sub Form_Activate()
T1 = apiTimeGetTime()
Me.myList.RowSource = Me.myList.RowSource & ";Form_Activate: " & ";" & T1 & ";" & T1 - T0
End Sub
Private Sub Form_Current()
T1 = apiTimeGetTime()
Me.myList.RowSource = Me.myList.RowSource & ";Form_Current: " & ";" & T1 & ";" & T1 - T0
End Sub
Private Sub Form_Load()
T1 = apiTimeGetTime()
Me.myList.RowSource = Me.myList.RowSource & ";Form_Load: " & ";" & T1 & ";" & T1 - T0
End Sub
Private Sub Form_Resize()
T1 = apiTimeGetTime()
Me.myList.RowSource = Me.myList.RowSource & ";Form_Resize: " & ";" & T1 & ";" & T1 - T0
End Sub
'51. Вызов таймера с применением AddressOf
'#########################
Private hTimer As Long ' Указатель на запущенный процесс
Private Const TIME_ONESHOT = 0 ' Событие случается однажды
Private Const TIME_PERIODIC = 1 ' Событие случается через uDelay миллисекунд
' Запуск процесса
Private Declare Function apiTimeSetEvent Lib "winmm.dll" Alias "timeSetEvent" _
(ByVal uDelay As Long, _
ByVal uResolution As Long, _
ByVal lpFunction As Long, _
ByVal dwUser As Long, _
ByVal uFlags As Long) As Long
' Уничтожение процесса
Private Declare Function apiTimeKillEvent Lib "winmm.dll" Alias "timeKillEvent" _
(ByVal uID As Long) As Long
' Функция запуска событий
Private Sub butExec_Click()
Dim uDelay As Long
Dim uResolution As Long
Dim dwUser As Long
Dim fuEvent As Long
uDelay = Me.uDelay * 1000 ' Число секунд
uResolution = Me.uResolution
dwUser = Me.dwUser
uFlags = Me.uFlags ' uFlags = TIME_PERIODIC
hTimer = apiTimeSetEvent(uDelay, _
uResolution, _
AddressOf funTimerProc, _
dwUser, _
uFlags)
End Sub
' Программа для выполнения процесса таймера
Public Function funTimerProc(ByVal uID As Long, _
ByVal uMsg As Long, _
ByVal dwUser As Long, _
ByVal dw1 As Long, _
ByVal dw2 As Long) As Long
Dim frm As Form
Set frm = Forms("Example 07")
frm.Msg = "Время: " & Format(Time, "hh:nn:ss") & _
", ID= " & uID & _
", Msg=" & uMsg & _
", User=" & dwUser & _
", dw1=" & dw1 & _
", dw2=" & dw2 & vbNewLine & frm.Msg
funTimerProc = 0
' Debug.Print uID, uMsg, dwUser, dw1, dw2
End Function
'52. Системная информация о дисках
'#########################
' Запрашиваем информацию о диске
Private Declare Function apiGetDiskFreeSpace Lib "kernel32" Alias "GetDiskFreeSpaceA" _
(ByVal lpRootPathName As String, _
lpSectorsPerCluster As Long, _
lpBytesPerSector As Long, _
lpNumberOfFreeClusters As Long, _
lpTotalNumberOfClusters As Long) As Long
' Загрузка данных
Private Sub Form_Load()
On Error Resume Next
Me.myDrive.RowSource = funGetDrivers
Me.myDrive = Me.myDrive.Column( 0 , 0 )
myDrive_AfterUpdate
Err.Clear
End Sub
' Получаем информацию о диске системы
Private Function funInformationDisk()
Dim fs, dc, D, s As String
On Error Resume Next
s = ""
' 1. Получаем информацию из файловой системы
Set fs = CreateObject("Scripting.FileSystemObject")
Set dc = fs.Drives
For Each D In dc
If StrComp(D.DriveLetter, Left(myDrive, 1 ), vbTextCompare) = 0 Then
s = s & "Серийный номер: " & D.SerialNumber & ";"
s = s & "Емкость диска: " & Format(D.TotalSize, "#,0") & ";"
s = s & "Доступный объем диска: " & Format(D.AvailableSpace, "#,0") & ";"
s = s & "Свободное место на диске: " & Format(D.FreeSpace, "#,0") & ";"
s = s & "Метка тома: " & D.VolumeName & ";"
s = s & "Файловая система: " & D.FileSystem & ";"
Exit For
End If
Err.Clear
Next D
' 2. Получаем информацию из api интерфейса
Dim SectorsPerCluster As Long ' Секторов на клястер
Dim BytesPerSector As Long ' Байт на сектор
Dim NumberOfFreeClustors As Long ' Свободных клястеров
Dim TotalNumberOfClustors As Long ' Всего клястеров
' Запрашиваем свободное место
Call apiGetDiskFreeSpace(Left(Me.myDrive, 2 ), _
SectorsPerCluster, BytesPerSector, _
NumberOfFreeClustors, TotalNumberOfClustors)
s = s & "Число секторов на клястер: " & Format(SectorsPerCluster, "#,0") & ";"
s = s & "Число байт на сектор: " & Format(BytesPerSector, "#,0") & ";"
s = s & "Число свободных клястеров: " & Format(NumberOfFreeClustors, "#,0") & ";"
s = s & "Всего клястеров: " & Format(TotalNumberOfClustors, "#,0") & ";"
' Используя клястеры Вы можете определить
' a) Емкость диска = TotalNumberOfClustors * SectorsPerCluster * BytesPerSector
' b) Свободное место = NumberOfFreeClustors * SectorsPerCluster * BytesPerSector
' 3. Присваиваем источник данных
Me.myList.RowSource = s
Exit Function
End Function
' Заполняем список с информацией о дисках
Private Function funGetDrivers() As String
Dim fs, dc, D
Dim s As String
On Error GoTo 999
Err.Clear
funGetDrivers = ""
Set fs = CreateObject("Scripting.FileSystemObject")
Set dc = fs.Drives
For Each D In dc
Select Case D.driveType
Case 0 : s = "Неизвестная БД"
Case 1 : s = "Дискета"
Case 2 : s = "Жесткий диск"
Case 3 : s = "Сетевой диск"
Case 4 : s = "CD-ROM"
Case 5 : s = "RAM диск"
End Select
If D.IsReady Then
funGetDrivers = funGetDrivers & D.DriveLetter & ":\ - " & s & ";"
End If
Next
Exit Function
999 :
MsgBox Err.Description
Err.Clear
funGetDrivers = ""
End Function
' Обновляем информацию
Private Sub myDrive_AfterUpdate()
funInformationDisk
End Sub
'53. Управление текстовым буфером
'#########################
' Функции управления буфером
Private Declare Function IsClipboardFormatAvailable Lib "user32" _
(ByVal uFormat As Integer) As Integer
Private Declare Function apiOpenClipboard Lib "user32" Alias "OpenClipboard" _
(ByVal hwnd As Long) As Integer
Private Declare Function apiSetClipboardData Lib "user32" Alias "SetClipboardData" _
(ByVal uFormat As Integer, _
ByVal hData As Long) As Long
Private Declare Function apiGetClipboardData Lib "user32" Alias "GetClipboardData" _
(ByVal uFormat As Integer) As Long
Private Declare Function apiCloseClipboard Lib "user32" Alias "CloseClipboard" _
() As Integer
Private Declare Function apiEmptyClipboard Lib "user32" Alias "EmptyClipboard" _
() As Integer
' Функции управления памятью
Private Declare Function apiGlobalAlloc Lib "kernel32" Alias "GlobalAlloc" _
(ByVal uFlags As Integer, _
ByVal dwBytes As Long) As Long
Private Declare Function apiGlobalSize Lib "kernel32" Alias "GlobalSize" _
(ByVal hMem As Long) As Integer
Private Declare Function apiGlobalLock Lib "kernel32" Alias "GlobalLock" _
(ByVal hMem As Long) As Long
Private Declare Sub apiMoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
(ByVal strDest As Any, _
ByVal lpSource As Any, _
ByVal Length As Long)
Private Declare Function apiGlobalUnlock Lib "kernel32" Alias "GlobalUnlock" _
(ByVal hMem As Long) As Integer
Private Declare Function apiGlobalFree Lib "kernel32" Alias "GlobalFree" _
(ByVal hMem As Long) As Long
' api-Константы памяти
Private Const GMEM_FIXED = &H0
Private Const GMEM_MOVEABLE = &H2
Private Const GMEM_NOCOMPACT = &H10
Private Const GMEM_NODISCARD = &H20
Private Const GMEM_ZEROINIT = &H40
Private Const GMEM_MODIFY = &H80
Private Const GMEM_DISCARDABLE = &H100
Private Const GMEM_NOT_BANKED = &H1000
Private Const GMEM_SHARE = &H2000
Private Const GMEM_DDESHARE = &H2000
Private Const GMEM_NOTIFY = &H4000
Private Const GMEM_LOWER = GMEM_NOT_BANKED
Private Const GMEM_VALID_FLAGS = &H7F72
Private Const GMEM_INVALID_HANDLE = &H8000
Private Const GMEM_TEXT = (GMEM_MOVEABLE Or GMEM_DDESHARE)
' api-Форматы буфера
Private Const CF_TEXT = 1
Private Const CF_BITMAP = 2
Private Const CF_METAFILEPICT = 3
Private Const CF_SYLK = 4
Private Const CF_DIF = 5
Private Const CF_TIFF = 6
Private Const CF_OEMTEXT = 7
Private Const CF_DIB = 8
Private Const CF_PALETTE = 9
Private Const CF_PENDATA = 10
Private Const CF_RIFF = 11
Private Const CF_WAVE = 12
Private Const CF_UNICODETEXT = 13
Private Const CF_ENHMETAFILE = 14
'==============================================================
' Копируем текст в буфер
'
Function CopyText(strText As String) As Variant
Dim hMem As Long
Dim lpMem As Long
Dim l As Long
' Выделение памяти
l = Len(strText) + 1 ' Длина строки с учетом символа \0 (c++)
hMem = apiGlobalAlloc(GMEM_TEXT, l) ' Память для буфера
' Управление памятью
lpMem = apiGlobalLock(hMem) ' Блокируем часть памяти
Call apiMoveMemory(lpMem, strText, l) ' Копируем строку в память
Call apiGlobalUnlock(hMem) ' Разблокируем память
' Управление буфером
Call apiOpenClipboard( 0 &) ' Открываем буфер
Call apiEmptyClipboard ' Очищаем буфер
Call apiSetClipboardData(CF_TEXT, hMem) ' Загружаем текст
Call apiCloseClipboard ' Закрываем буфер
' Освобождаем память
Call apiGlobalFree(hMem)
End Function
'==============================================================
' Получаем текст из буфера
'
Public Function GetText() As Variant
Dim hMem As Long
Dim lpMem As Long
Dim s As String
Dim l As Long
' Проверяем формат буфера
If Not CBool(IsClipboardFormatAvailable(CF_TEXT)) Then
Exit Function
End If
' Работаем с буфером и памятью
Call apiOpenClipboard( 0 &) ' Открываем буфер
hMem = apiGetClipboardData(CF_TEXT) ' Получаем заголовок данных в буфере
l = apiGlobalSize(hMem) ' Определяем размер строки
s = Space$(l) ' Выделение памяти для строки
lpMem = apiGlobalLock(hMem) ' Блокируем память
Call apiMoveMemory(s, lpMem, l) ' Копируем информацию из буфера в строку
Call apiGlobalUnlock(hMem) ' Разблокирование памяти
Call apiCloseClipboard ' Закрываем буфер
' Возвращаем результат
GetText = Left$(s, InStr( 1 , s, Chr$( 0 )) - 1 )
End Function
'54. Получение сетевого имени пользователя
'#########################
Private Declare Function apiGetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
(ByVal lpBuffer As String, nSize As Long) As Long
' Возвращает сетевое имя пользователя
Function funGetUserName() As String
Dim BufSize As Long, strUserName As String * 255 , Status As Long
On Error GoTo 999
BufSize = 255
Status = apiGetUserName(strUserName, BufSize)
If Status = 1 Then
funGetUserName = Left$(strUserName, InStr(strUserName, Chr( 0 )) - 1 )
Else
funGetUserName = ""
End If
Exit Function
999 :
MsgBox Err.Description
End Function
' Функция запуска событий
Private Sub butExec_Click()
Me.Msg = "Локальное имя: " & funGetUserName & vbNewLine & _
"Сетевое имя: " & NetUserID
End Sub
'54. Работа с FTP протоколом
'#########################
Private Declare Function FtpGetFile _
Lib "wininet.dll" Alias "FtpGetFileA" ( _
ByVal hFtpSession As Long, _
ByVal lpszRemoteFile As String, _
ByVal lpszNewFile As String, _
ByVal fFailIfExists As Boolean, _
ByVal dwFlagsAndAttributes As Long, _
ByVal dwFlags As Long, _
ByVal dwContext As Long) As Boolean
Private Declare Function InternetOpen _
Lib "wininet.dll" Alias "InternetOpenA" ( _
ByVal sAgent As String, _
ByVal nAccessType As Long, _
ByVal sProxyName As String, _
ByVal sProxyBypass As String, _
ByVal nFlags As Long) As Long
Private Declare Function InternetConnect _
Lib "wininet.dll" Alias "InternetConnectA" ( _
ByVal hInternetSession As Long, _
ByVal sServerName As String, _
ByVal nServerPort As Integer, _
ByVal sUserName As String, _
ByVal sPassword As String, _
ByVal nService As Long, _
ByVal dwFlags As Long, _
ByVal dwContext As Long) As Long
hINetSession = InternetOpen("MyFTPClient", 0 , vbNullString, vbNullString, 0 )
hSession = InternetConnect(hINetSession, "ftp.microsoft.com", _
"21", "anonymous", "guest", INTERNET_SERVICE_FTP, 0 , 0 )
Private Const INTERNET_SERVICE_FTP = 1
Private Const INTERNET_SERVICE_GOPHER = 2
Private Const INTERNET_SERVICE_HTTP = 3
Private Declare Function FtpGetFile _
Lib "wininet.dll" Alias "FtpGetFileA" ( _
ByVal hFtpSession As Long, _
ByVal lpszRemoteFile As String, _
ByVal lpszNewFile As String, _
ByVal fFailIfExists As Boolean, _
ByVal dwFlagsAndAttributes As Long, _
ByVal dwFlags As Long, _
ByVal dwContext As Long) As Boolean
If FtpGetFile(hSession, "dirmap.htm", "c:\dirmap.htm", False, 0 , 1 , 0 ) = False Then
MsgBox "Call to FtpGetFile Failed!"
End If
Пункт четвертый, заключительный: закрываем Хендлы
Private Declare Function InternetCloseHandle _
Lib "wininet.dll" (ByVal hInet As Long) As Integer
Call InternetCloseHandle(hSession)
Call InternetCloseHandle(hINetSession)
Private Declare Function FtpPutFile _
Lib "wininet.dll" Alias "FtpPutFileA" ( _
ByVal hFtpSession As Long, _
ByVal lpszLocalFile As String, _
ByVal lpszRemoteFile As String, _
ByVal dwFlags As Long, _
ByVal dwContext As Long) As Boolean
If FtpPutFile(hSession, "c:\MyFile.txt", "shared.txt", 1 , 0 ) = False Then
MsgBox "The call to FtpPutFile failed."
End If
Private Declare Function FtpDeleteFile _
Lib "wininet.dll" Alias "FtpDeleteFileA" ( _
ByVal hFtpSession As Long, _
ByVal lpszFileName As String) As Boolean
ПЕРЕИМЕНОВАНИЕ
Private Declare Function FtpRenameFile _
Lib "wininet.dll" Alias "FtpRenameFileA" ( _
ByVal hFtpSession As Long, _
ByVal lpszExisting As String, _
ByVal lpszNewName As String) As Boolean
Private Declare Function FtpFindFirstFile _
Lib "wininet.dll" Alias "FtpFindFirstFileA" ( _
ByVal hFtpSession As Long, _
ByVal lpszSearchFile As String, _
ByRef lpFindFileData As WIN32_FIND_DATA, _
ByVal dwFlags As Long, _
ByVal dwContent As Long) As Long
Private Declare Function InternetFindNextFile _
Lib "wininet.dll" Alias "InternetFindNextFileA" ( _
ByVal hFind As Long, _
ByRef lpvFindData As WIN32_FIND_DATA) As Long
Private Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * 260
cAlternate As String * 14
End Type
Подструктура FileName:
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Private Sub ListFiles()
Dim hFile As Long ' This is a file handle
Dim fd As WIN32_FIND_DATA
hFile = FtpFindFirstFile(hSession, "*.*", fd, 0 , 0 )
If hFile = 0 Then
If Err.LastDllError = ERROR_NO_MORE_FILES Then
MsgBox "No files found"
Exit Sub
Else
MsgBox "Some error occurred"
Exit Sub
End If
End If
Do
List1.AddItem fd.cFileName
Loop While InternetNextFile(hFile, fd) <> 0
'Close the file handle
Call InternetCloseHandle(hFile)
End Sub
'55. Получ MAC адрес сетевой карты.
'#########################
Option Explicit
Public Const NCBASTAT As Long = &H33
Public Const NCBNAMSZ As Long = 16
Public Const HEAP_ZERO_MEMORY As Long = &H8
Public Const HEAP_GENERATE_EXCEPTIONS As Long = &H4
Public Const NCBRESET As Long = &H32
Public Type NET_CONTROL_BLOCK 'NCB
ncb_command As Byte
ncb_retcode As Byte
ncb_lsn As Byte
ncb_num As Byte
ncb_buffer As Long
ncb_length As Integer
ncb_callname As String * NCBNAMSZ
ncb_name As String * NCBNAMSZ
ncb_rto As Byte
ncb_sto As Byte
ncb_post As Long
ncb_lana_num As Byte
ncb_cmd_cplt As Byte
ncb_reserve( 9 ) As Byte ' Reserved, must be 0
ncb_event As Long
End Type
Public Type ADAPTER_STATUS
adapter_address( 5 ) As Byte
rev_major As Byte
reserved0 As Byte
adapter_type As Byte
rev_minor As Byte
duration As Integer
frmr_recv As Integer
frmr_xmit As Integer
iframe_recv_err As Integer
xmit_aborts As Integer
xmit_success As Long
recv_success As Long
iframe_xmit_err As Integer
recv_buff_unavail As Integer
t1_timeouts As Integer
ti_timeouts As Integer
Reserved1 As Long
free_ncbs As Integer
max_cfg_ncbs As Integer
max_ncbs As Integer
xmit_buf_unavail As Integer
max_dgram_size As Integer
pending_sess As Integer
max_cfg_sess As Integer
max_sess As Integer
max_sess_pkt_size As Integer
name_count As Integer
End Type
Public Type NAME_BUFFER
name As String * NCBNAMSZ
name_num As Integer
name_flags As Integer
End Type
Public Type ASTAT
adapt As ADAPTER_STATUS
NameBuff( 30 ) As NAME_BUFFER
End Type
Public Declare Function Netbios Lib "netapi32.dll" _
(pncb As NET_CONTROL_BLOCK) As Byte
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(hpvDest As Any, ByVal _
hpvSource As Long, ByVal _
cbCopy As Long)
Public Declare Function GetProcessHeap Lib "kernel32" () As Long
Public Declare Function HeapAlloc Lib "kernel32" _
(ByVal hHeap As Long, ByVal dwFlags As Long, _
ByVal dwBytes As Long) As Long
Public Declare Function HeapFree Lib "kernel32" _
(ByVal hHeap As Long, _
ByVal dwFlags As Long, _
lpMem As Any) As Long
Public Function GetMACAddress() As String
'запрашиваем MAC Адрес для сетевой карты
'возвращаем форматированную строку
Dim tmp As String
Dim pASTAT As Long
Dim NCB As NET_CONTROL_BLOCK
Dim AST As ASTAT
NCB.ncb_command = NCBRESET
Call Netbios(NCB)
'Для получения Media Access Control (MAC) адреса для сетевой карты
'программным путём, используется команда Netbios() -
'NCBASTAT с именем "*" в поле NCB.ncb_CallName (в 16-символьной строке).
NCB.ncb_callname = "* "
NCB.ncb_command = NCBASTAT
'Для машин с несколькими сетевыми картами Вам необходимо использовать
'номер LANA и выполнять команду NCBASTAT для каждого. LANA номер 0 всегда
'соответствует первому сетевому адаптеру. Конечно можно использовать LANA
'номер и для одного сетевого адаптера, но это будет считаться как
'неэффективное программирование.
NCB.ncb_lana_num = 0
NCB.ncb_length = Len(AST)
pASTAT = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS _
Or HEAP_ZERO_MEMORY, NCB.ncb_length)
If pASTAT = 0 Then
Debug.Print "memory allocation failed!"
Exit Function
End If
NCB.ncb_buffer = pASTAT
Call Netbios(NCB)
CopyMemory AST, NCB.ncb_buffer, Len(AST)
tmp = Format$(Hex(AST.adapt.adapter_address( 0 )), "00") & " " & _
Format$(Hex(AST.adapt.adapter_address( 1 )), "00") & " " & _
Format$(Hex(AST.adapt.adapter_address( 2 )), "00") & " " & _
Format$(Hex(AST.adapt.adapter_address( 3 )), "00") & " " & _
Format$(Hex(AST.adapt.adapter_address( 4 )), "00") & " " & _
Format$(Hex(AST.adapt.adapter_address( 5 )), "00")
HeapFree GetProcessHeap(), 0 , pASTAT
GetMACAddress = tmp
End Function
'Код формы.
'Добавьте в форму кнопку (Command1), и текстовое поле (Text1). Метки и фреймы не обязательны. Добавьте в событие кнопки следующий код:
Option Explicit
Private Sub Command1_Click()
Text1 = GetMACAddress()
End Sub
'56. Реестр и Windows API
'#########################
'В ранних версиях Windows, все её приложения хранили необходимую для запуска и работы информацию в файлах инициализации. С развитием ОС информации, необходимой для сохранения стало так много, что возникла необходимость в новом способе её хранения - реестре. Реестр, - это своеобразная база данных для приложений Windows. Его структура напоминает файловую систему. (не верите посмотрите через regedit.exe только ничего не меняйте). Вообще реестр считают несомненной альтернативой INI-файлам, но я думаю, что эти две технологии имеют наибольшую мощность только при их совмещении.
'В Visual Basic есть функции для работы с реестром( GetSetting,SaveSetting) но их возможности ограничены. Они могут работать с реестром только в разделе HKEY_CURRENT_USER\Software\VB and VBA Programms, и способны только читать и записывать. Для начинающего программиста это неплохо, даже хорошо - меньше возможностей навредить.На самом деле Windows может намного больше. Расширить возможности VB, позволяет Windows API.
'Windows обладает большим набором функций для работы с реестром, сами по себе GetSetting и SaveSetting тоже вызывают их. С помощью этих функций, вы можете создавать разделы, в любой части реестра, а затем удалять их :), подключать реестр через сеть, сохранять разделы в файле и т.д.
'В качестве примера, мы создадим класс, для работы с реестром через Windows API (насколько я знаю в Borland Delphi, нечто подобное уже есть, и один знакомый программист очень этим гордится :) ). Этот класс может работать только со строковыми данными. Я посчитал, что если Вам понадобится больше, Вы сможете сделать это сами. Кроме того класс даёт возможность удалять лишние разделы, и параметры. Работу с реестром через сеть, и остальные возможности я исключил, так как этот класс задуман как расширение Basic'овских функций для работы с реестром. Остальные операции будут заключены в другой класс, который должен будет реализовать все возможности Windows API в работе с реестром.
'Итак, хватит лирики, приступим к работе. Создадим новый модуль класса и назовём его RegistryExClass(совсем как в API, RegSetValue,RegSetValueEx). После этого приступим к объявлению необходимых функций.Я рассмотрю только особенные, остальные найдёте в API Text Viewer. (RegOpenKey, RegDeleteValue, RegDeleteKey, RegCloseKey, RegCreateKey)
Private Declare Function RegQueryValueExS Lib "advapi32.dll" _
Alias "RegQueryValueExA" ( _
ByVal hkey As Long, _
ByVal lpValueName As String, _
ByVal lpReserved As Long, _
lpType As Long, _
ByVal lpData As String, _
lpcbData As Long) As Long
Private Declare Function RegSetValueExS Lib "advapi32.dll" _
Alias "RegSetValueExA" ( _
ByVal hkey As Long, _
ByVal lpValueName As String, _
ByVal Reserved As Long, _
ByVal dwType As Long, _
ByVal lpData As String, _
ByVal cbData As Long) As Long
'
'Что здесь особенного, спросите Вы. Объясняю: Как я уже сказал мой класс работает только со строками. Приведённые выше функции, в оригинальном объявлении не имеют чётко определённого типа данных(lpData As Any). При попытке использовать такое объявление, я получал ошибку "Out Of Memory". Как видно в листинге, я объявил lpData как строку, хотя имею возможность присвоить любой тип. Беда в том, что VB не поймёт Вас при попытке объявить две функции. Чтобы обойти это, я и объявил функции с оконаниями "-S". И теперь в класс можно будет добавить ещё функции для работы с различными типами.
'Ещё по той же теме. Некоторые функции для работы с реестром имеют параметры типа SECURITY_ATTRIBUTES. Если эти параметры Вам не нужны, то объявите их как Long, и передавайте ноль.
'Теперь объявим константы.
'Объявив эти константы таким способом, Вы дадите
'пользователю класса возможность выбирать из списка
'значение параметра
Public Enum HKEY_CONSTANTS
HKEY_CLASSES_ROOT = &H80000000
HKEY_CURRENT_CONFIG = &H80000005
HKEY_CURRENT_USER = &H80000001
HKEY_DYN_DATA = &H80000006
HKEY_LOCAL_MACHINE = &H80000002
HKEY_PERFORMANCE_DATA = &H80000004
HKEY_USERS = &H80000003
End Enum
'Ну ещё константа, для строкового типа
Private Const REG_SZ = 1
'Теперь создадим методы для чтения/записи параметров
'~~~~~~.GetString Функция
Public Function GetString( _
ByVal HomeKey As HKEY_CONSTANTS, _
ByVal KeyName As String, _
ByVal ValueName As String) As String
'Handle раздела реестра
Dim hkey As Long
'переменная для хранения значения
Dim sData As String
'Результат работы API функций
Dim lres As Long
'Тип возвращаемого значения
Dim lDataType As Long
'переменная для хранения длины строки
Dim lDlen As Long
'Открываем Раздел
lres = RegOpenKey(HomeKey, KeyName, hkey)
'Если вернулся не ноль - ошибка, выходим
If lres <> 0 Then GetRegString = vbNullString: Exit Function
'Продолжаем, заполняем строку пробелами.
sData = String$( 64 , 32 ) & Chr$( 0 )
lDlen = Len(sData)
'Читаем значение
lres = RegQueryValueExS(hkey, ValueName, 0 , lDataType, sData, lDlen)
'опять проверка на ошибку
If lres <> 0 Then GetRegString = vbNullString: Exit Function
'проверяем тип полученных данных
If lDataType = REG_SZ Then
GetString = Left$(sData, lDlen - 1 )
Else
GetString = vbNullString
End If
'и закрываем раздел
lres = RegCloseKey(hkey)
End Function
'~~~~~.SaveString Метод
Public Sub SaveString( _
ByVal HomeKey As HKEY_CONSTANTS, _
ByVal KeyName As String, _
ByVal ValueName As String, _
ByVal Data As String)
'Handle для корневого раздела
Dim hkey As Long
'Handle для изменяемого раздела
Dim hSubKey As Long
'Результат работы функции
Dim lres As Long
'Открываем корневой раздел
lres = RegOpenKey(HomeKey, vbNullString, hkey)
'Создаём(если есть открываем) нужный раздел
lres = RegCreateKey(HomeKey, KeyName, hSubKey)
'Пишем данные
lres = RegSetValueExS(hSubKey, ValueName, 0 , _
REG_SZ, Data + Chr$( 0 ), Len(Data) + 1 )
'и закрываем всё открытое
lres = RegCloseKey(hSubKey)
lres = RegCloseKey(hkey)
End Sub
'Метод GetString всего лишь читает параметр из реестра. SaveString - имеет больше возможностей. С его помощью Вы можете создать пустой раздел. Для этого вызовите его, установив значение ValueName и Data равное пустой строке. Если хотите установить для раздела значение по умолчанию присвойте Data нужное значение, при нулевом(vbNullString) ValueName.
'Теперь поработаем с удалением.
'~~~~~~.DeleteValue Метод
Public Sub DeleteValue( _
ByVal HomeKey As HKEY_CONSTANTS, _
ByVal KeyName As String, _
ByVal ValueName As String)
'Handle для изменяемого раздела
Dim hkey As Long
'Результат API функции
Dim lres As Long
'открываем нужные раздел
lres = RegOpenKey(HomeKey, KeyName, hkey)
'проверяем на ошибку
If lres <> 0 Then Exit Sub
'удаляем параметр
lres = RegDeleteValue(hkey, ValueName)
'закрываем
lres = RegCloseKey(hkey)
End Sub
'~~~~~~.DeleteKey
Public Sub DeleteKey( _
ByVal HomeKey As HKEY_CONSTANTS, _
ByVal KeyName As String)
'результат APi функции
Dim lres As Long
'Удаляем раздел из корневого
lres = RegDeleteKey(HomeKey, KeyName)
End Sub
'57. способ получения скриншота
'#########################
'Способ основан на симуляции нажатия клавиши Print Screen (Const vbKeySnapshot = 44 (&H2C)), - для копирования изображения экрана, и методе Clipboard.GetData(vbCFBitmap), - для дальнейшего получения изображения в Picture (Picture Box).
'Объявляем в General Form1:
Private Declare Sub keybd_event Lib "user32" _
(ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, _
ByVal dwExtraInfo As Long)
Dim A As Integer
'в Properties Form1 устанавливаем BorderStyle в 0-None, для того, чтобы в
'момент получения <фотографии> экрана, детали формы не попали в "кадр"
Private Sub Form_Load()
'делаем форму невидимой, но при этом оставляем активными все 'компоненты
Form1.height = 0
Timer1.Interval = 1
'очищаем Clipboard
Clipboard.Clear
'копируем изображение экрана
keybd_event vbKeySnapshot, 1 , 0 &, 0 &
End Sub
Private Sub Timer1_Timer()
A = A + 1
If A = 2 Then
'вклеиваем изображение в картинку
Picture1.Picture = Clipboard.GetData(vbCFBitmap)
'задаём размеры формы и картинки
Form1.Width = Screen.Width * 0 . 8
Form1.height = Screen.height * 0 . 8
Form1.Left = (Screen.Width - Width) / 2
Form1.Top = (Screen.height - height) / 2
Picture1.height = Form1.ScaleHeight * 1
Picture1.Width = Form1.ScaleWidth * 1
Picture1.Left = (Form1.Width - Picture1.Width) / 2
Picture1.Top = (Form1.height - Picture1.height) / 2
End If
If A = 2 Then
'очищаем Clipboard
Clipboard.Clear
'выключаем Timer1
Timer1.Enabled = False
End If
End Sub
'для выхода из программы
Private Sub Picture1_Click()
End
End Sub
'58. Техника программирования сложных окон в Visual Basic
'#########################
'Многие из Вас наверняка видели в Windows программах окна нестандартной формы (круглые, треугольные и т.д.) и задавали себе вопрос: как мне сделать такое окно? Если прочитать документацию по Visual Basic, то можно сделать вывод, что стандартные средства языка не предоставляют такой возможности. А что же делать, если очень хочется? Тогда следует вспомнить, что в распоряжении программиста на VB есть еще и Windows API, который должен нам в этом помочь.
'Теоретические основы
'
'Для начала давайте разберемся, как это можно сделать теоретически. Из документации Windows видно, что каждое окно в системе описывается множеством параметров, из которых нас с Вами интересует <видимая область окна>. Видимая область окна в системе, создаваемое Visual Basic <по умолчанию> имеет вид прямоугольника, но, в принципе, ничто не мешает изменить форму этой области. Данная область окна описывается с помощью специального объекта, который называется Region. Регион можно представить в виде поверхности, ограниченной координатами, описываемыми угловые точки этой области. Проще говоря, можно описать область любой формы, затем создать из неё, с помощью специальных функций, регион и <прикрепить> его к нужому нам окну.
'
'Существует несколько функций Windows API для создания регионов, основными из которых являются следующие:
'CombineRgn - Комбинирует два региона между собой
'CreateEllipticRgn - Создает регион в виде эллипса или окружности
'CreatePolygonRgn - Создает регион в виде многоугольника
'CreateRectRgn - Создает прямоугольный регион
'CreateRoundRectRgn - Создает регион со скругленными краями из прямоугольной области
'SetWindowRgn - Прикрепляет регион к указанному окну
'
'Я не буду приводить подробное описание этих функций, так как его можно найти в описании Win32 API. Кроме этих функций существуют ещё несколько функций для работы с регионами, но нам они не потребуются.
'Создание простых нестандартных окон
'
'Теперь, когда нам известны основные функции, для создания регионов, мы можем применить полученные знания на практике. Загрузите проект pTestRgn и внимательно изучите его код. В этом проете, для изменения формы окна на овальную, используется всего три строки кода и три функции Win32 API. Вначале с помощью CreateEllipticRgn создается регион, затем он прикрепляется к окну и, наконец, завершающая фаза удаление, ставшего ненужным, созданного нами региона. Если же Вы не удалите ненужный Вам больше объект, то Windows, создав регион для Вас будет хранить его в своих <недрах> и ждать дальнейших указаний по его использованию. В общем, нехорошо <захламлять> выделенную память, и настигнет Вас кара небесная, и затянется небо тучами синими, и будет страшный суд над всеми неверующими: Короче код выглядит так:
Private Sub cmbCreateOval_Click()
Dim lRgn As Long
lRgn = CreateEllipticRgn( 0 , 0 , Me.ScaleWidth / Screen.TwipsPerPixelX, _
Me.ScaleHeight / Screen.TwipsPerPixelY)
SetWindowRgn Me.hwnd, lRgn, True
DeleteObject lRgn
End Sub
'Так же всё просто, скажете Вы? Да, на первый взгляд всё очень просто, но это только кажется. Тот пример, который Вы только что видели, почти не имеет практического применения в настоящих приложениях Windows. Кому же нужно просто овальное окно, которое к тому же жестко задается на этапе программирования? А вот окно, которое свободно могло бы менять свою форму вполне может потребоваться. Примеры? Пожалуйста, WinAmp, Помощник в Microsoft Office и другие программы. Как же там всё это реализовано? Давайте разберемся с таким применением регионов.
'Создание сложных нестандартных окон
'
'Допустим, что у нас есть рисунок в BMP формате, из которого нужно сделать форму, а белый цвет (например) на нём означает <пустоту>. Как же сделать форму? Очень просто, нужно взять все <не белые> пиксели на рисунке, создать из их координат регион и прикрепить его к нужному нам окну. Анализировать пиксели можно GetPixel, эта функция по координатам возвращает его цвет. Давайте теперь напишем такой алгоритм для анализа BMP матрицы. Я думаю, что такой алгоритм Вам известен, и мы не будем его подробно разбирать, отмечу только, что анализ производится построчно и Pixel-и добавляются в регион не по одному, а группами построчно. Такой подход сильно экономит ресурсы процессора, выигрыш в производительности достигает 100%.
Public Function lGetRegion(pic As PictureBox, lBackColor As Long) As Long
Dim lRgn As Long
Dim lSkinRgn As Long
Dim lStart As Long
Dim lX As Long
Dim lY As Long
Dim lHeight As Long
Dim lWidth As Long
'создаем пустой регион, с которого начнем работу
lSkinRgn = CreateRectRgn( 0 , 0 , 0 , 0 )
With pic
'подсчитаем размеры рисунка в Pixel
lHeight = .height / Screen.TwipsPerPixelY
lWidth = .Width / Screen.TwipsPerPixelX
For lX = 0 To lHeight - 1
lY = 0
Do While lY < lWidth
'ищем нужный Pixel
Do While lY < lWidth And GetPixel(.hdc, lY, lX) = lBackColor
lY = lY + 1
Loop
If lY < lWidth Then
lStart = lY
Do While lY < lWidth And GetPixel(.hdc, lY, lX) <> lBackColor
lY = lY + 1
Loop
If lY > lWidth Then lY = lWidth
'нужный Pixel найден, добавим его в регион
lRgn = CreateRectRgn(lStart, lX, lY, lX + 1 )
CombineRgn lSkinRgn, lSkinRgn, lRgn, RGN_OR
DeleteObject lRgn
End If
Loop
Next
End With
lGetRegion = lSkinRgn
End Function
'Итак, для проверки на практике этого алгоритма загрузите пример pTestRgnSkin и внимательно изучите его код. В этом проекте нужный нам рисунок, для удобства, <зашит> в файле ресурсов, кроме того проект запускается процедурой Main, в которой и происходят все преобразования. Вначале загружается форма, затем в PictureBox из ресурсов загружается нужный нам рисунок, далее вызывается функция, которая создает регион и, наконец, завершающий этап - прикрепление региона к нужному нам окну. Для удобства здесь же вызывается функция, помещающая окно <поверх всех>, чтобы оно <не потерялось> у Вас на рабочем столе Windows. Кроме того, для нормальной работы программы необходимо, чтобы для PictureBox свойство AutoRedraw было установленно в True, иначе ничего не получится.
Sub Main()
Dim lRgn As Long
Load frmTestRgnSkin
frmTestRgnSkin.pic.Picture = LoadResPicture( 101 , vbResBitmap)
lRgn = lGetRegion(frmTestRgnSkin.pic, vbWhite)
SetWindowRgn frmTestRgnSkin.hwnd, lRgn, True
DeleteObject lRgn
frmTestRgnSkin.Show
SetFormPosition frmTestRgnSkin.hwnd, True
End Sub
'Теперь можно запускать проект... О, знакомое лицо, скажите Вы, это же <Скрепыш> из Microsoft Office. Да, похож, но не совсем, <Скрепыш> двигается, а этот нет. Что же нужно сделать, чтобы это окно динамически изменяло свою форму по рисунку, отображаемому в данный момент времени в PictureBox?
'Динамическое изменение формы окна
'
'Существуют программы в которых необходимо динамически во время работы изменять форму окна (например анимированный персонаж из Microsoft Office). Все это не очень сложно реализовать, нужно в событие PictureBox.Change добавить следующий код:
lRgn = lGetRegion(frmTestRgnSkin.pic, vbWhite)
SetWindowRgn frmTestRgnSkin.hwnd, lRgn, True
DeleteObject lRgn
SetFormPosition frmTestRgnSkin.hwnd, True
'В принципе всё готово, осталось только добавить код для изменения картинки на форме, и <Скрепыш> оживёт. В нашем примере изменять рисунок будем в Timer циклически, т.е. анимация будет непрерывна, так проще. Итак, добавим на форму Timer и поместим <в него> небольшой код, отвечающий за изменения рисунка в PictureBox. Рисунков в файле ресурсов десять штук, поэтому I должно изменяться от 101 до 110. Код изменения выглядит так:
Static i As Long
If i < 101 Then i = 101
If i > 110 Then i = 101
frmAnimateForm.pic.Picture = LoadResPicture(i, vbResBitmap)
i = i + 1
'Готово, можно запускать проект, и если Вы счастливый обладатель Pentium III или Athlon, то Вам улыбнется удача, так как <Скрепыш> будет двигаться. Но если Ваш процессор Pentium II и ниже, то компьютер не сможет выполнять необходимые расчеты за нужное нам время, так как для плавной анимации необходимо (для нашего случая) показывать порядка 15 кадров в секунду, а точнее каждые 80 милисекунд по кадру и ещё оставлять время для других задач компьютера. Как мы видим наши алгоритмы явно не тянут для таких задач и предназначены для <работ> не требующих таких быстрых изменений формы окна, так как, например на Celeron 333 один кадр формируется около 100 милисекунд. Что же делать?
'Оптимизация алгоритма для быстрой анимации
'
'Анализ работы алгоритма показывает, что наибольшие затраты времени приходятся на функцию GetPixel. Это происходит потому, что анализ картинки идет непосредственно на экране. Единственный путь увеличения быстродействия алгоритма, это перенос анализа в память компьютера и использование при этом Win 32 API. Такие алгоритмы существуют, но это тема отдельного разговора, скажу только, что для оптимизации работы алгоритм пишется отдельно для каждой глубины цвета и при применении такой схемы быстродействие увеличивается почти в четыре раза и позволяет делать практически любую анимацию.
'58. Хранитель Экрана на Visual Basic
'#########################
'Хорош Visual Basic тем, что он позволяет создавать хранители экрана. Для этого нужно всего лишь создать проект с одной или несколькими формами, простым кодом, и откомпилировать его в файл с расширением *.Scr в рабочий каталог Windows.
'
'Как я думаю уже понятно, весь фокус состоит в коде. Его мы сейчас разберём, но сначала создадим форму. Разместим на ней таймер, и установим некоторые cвойства. (BorderStyle = None, WindowState = Maximized,Name = frmSSaver).Теперь приступаем к созданию кода. Сначала, как и всегда нам нужно объявить все необходимые переменные:
Option Explicit
Private DDC As Long 'Переменная для хранения хэндла Рабочего стола
Private BlockX As Long 'Размер закрашиваемого кусочка по горизонтали
Private BlockY As Long 'Размер закрашиваемого кусочка по вертикали
Private Quit As Boolean 'Флаг завершения
Private OldX As Single 'переменные для хранения
Private OldY As Single 'координат мыши
Const AppName = "VB Screen Saver" 'Имя программы в реестре
'Так как вся работа выполняется в цикле таймера, для выхода используется флаг Quit. Кстати о самой работе. Весь основной код Хранителя экрана прост как всё гениальное(какой я скромный правда?):
Private Sub Timer1_Timer()
'Код работы Хранителя экрана
Dim X As Long, Y As Long
X = (Rnd * Screen.Width) / Screen.TwipsPerPixelX
Y = (Rnd * Screen.height) / Screen.TwipsPerPixelY
Me.Line (X, Y)-Step(BlockX, BlockY), Me.BackColor, BF
If Quit Then
'Если Выход то...
Form_Unload 0
End If
End Sub
'Таймер обеспечивает рисование на форме и выход если флаг Quit установлен, но перед тем как рисовать необходимо сохранить изображение экрана на форме и "спрятать" мышь:
Private Sub Form_Load()
'Гашение курсора
ShowCursor False
'Чтение установок
If CLng(GetSetting(AppName, Chr$( 0 ), "BackColor", "-1")) = - 1 Then
Me.BackColor = GetSysColor(COLOR_BACKGROUND)
Else
Me.BackColor = CLng(GetSetting(AppName, Chr$( 0 ), "BackColor", "0"))
End If
BlockX = CLng(GetSetting(AppName, Chr$( 0 ), "XSize", 16 ))
BlockY = CLng(GetSetting(AppName, Chr$( 0 ), "YSize", 8 ))
Timer1.Interval = CLng(GetSetting(AppName, Chr$( 0 ), "Time", "100"))
'Получение описателя рабочего стола
DDC = GetWindowDC(GetDesktopWindow)
'Сохранение экрана на форме
BitBlt Me.hdc, 0 , 0 , XtoP(Screen.Width), YtoP(Screen.height), DDC, 0 , 0 , vbSrcCopy
End Sub
'
'При загрузке формы, программа читает из реестра параметры с помощью функций VB и, с помощью Windows API, убирает с экрана курсор мыши(мышь всё равно активна) и сохраняет экран на форме. Все объявления функций API, я разместил в отдельном модуле . Кстати этот модуль отвечает ещё за кое-какие операции, но об этом позже.
'
'Итак у нас есть код для подготовки формы, и код цикла рисования. Но если не установить флаг выхода цикл будет бесконечен. Поэтому используятся события формы MouseMove и KeyDown.
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
'Выход если двигалась мышь
If OldX = 0 Or OldY = 0 Then OldX = X: OldY = Y
If OldX <> X Or OldY <> Y Then Quit = True
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Quit = True 'Выход если нажата клавиша
End Sub
'Я думаю особо сложного в этом коде ничего нет. Вот только переменные OldX и OldY я объявил как доступные по всему модулю. Но чтобы эти переменные не сбрасывались при завершении процедуры обработки MouseMove, можно объявить их внутри неё с помощью оператора Static я не использовал его просто потому что он мне не очень нравиться.
'
'Продолжим: флаг Quit у нас устанавливается. Как Вы, надеюсь, помните при этом в цикле таймера вызывается процедура Form_Unload. В этой процедуре, отменяются все установки сделанные при загрузке формы.
Private Sub Form_Unload(Cancel As Integer)
ShowCursor True 'Восстановление курсора
ReleaseDC GetDesktopWindow, DDC 'Освобожление Хэндла экрана
End 'Собственно выход
End Sub
'В итоге получили работающий (во всяком случае у меня) код простенького Хранителя экрана. Но если его сейчас откомпилировать в *.scr файл, получим суррогат, который будет сложно использовать(Если хотите попробуйте выбрать такой "Хранитель" в окне свойств Рабочего стола.
'
'Особенность в том, что при запуске Хранителя экрана Windows передаёт ему параметры запуска в командной строке.
'
'Параметры командной строки передаваемые Windows
'/p - Хранитель экрана выбран в окне свойств рабочего стола. (На "мониторе" в окне должна демонстрироваться заставка)
'/c - Пользователь щёлкнул кнопку настройки параметров Хранителя экрана
'/s - Стандартный запуск, или щелчок по кнопке "Просмотр"
'/a - Пользователь хочет установить пароль.
'
'Именно для того чтобы разбирать тип запуска Хранителя экрана и существует модуль SSaver. (API-функции можно поместить и в код формы.)
Public Sub Main()
If App.PrevInstance Then Exit Sub
Select Case Left(LCase(Trim(Command$)), 2 )
Case "/s": frmSSaver.Show
Case "/c": frmProperties.Show
Case Else: End
End Select
End Sub
'В процедуре Main(не забудьте сделать её стартовой) как раз и разбираются эти параметры. Я использовал функцию Left, тем самым проигнорировав оставшиеся символы командной строки. На самом деле эти символы имеют важное значение. К примеру с параметром /p передаётся манипулятор(handle) "монитора" на окне свойств, что позволяет выводить изображение на него.
'59. Печать RTF
'#########################
'Как вам должно быть известно, то при выводе на печать RTF текста, печать начинается с начала страницы. И ничего с этим не поделаешь? Нет, кое что сделать можно:
в модуль
Public Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, _
ByVal nIndex As Long) As Long
Public Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" (ByVal hwnd As Long, _
ByVal Msg As Long, ByVal wp As Long, _
lp As Any) As Long
Public Declare Function CreateDC Lib "gdi32" _
Alias "CreateDCA" (ByVal _
lpDriverName As String, _
ByVal lpDeviceName As String, _
ByVal lpOutput As Long, _
ByVal lpInitData As Long) As Long
Public Const WM_USER As Long = &H400
Public Const EM_FORMATRANGE As Long = WM_USER + 57
Public Const EM_SETTARGETDEVICE As Long = WM_USER + 72
Public Const PHYSICALOFFSETX As Long = 112
Public Const PHYSICALOFFSETY As Long = 113
Public Type Rect
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public Type CharRange
cpMin As Long
cpMax As Long
End Type
Public Type FormatRange
hdc As Long
hdcTarget As Long
rc As Rect
rcPage As Rect
chrg As CharRange
End Type
Public Function PrintRichText(RTF As RichTextBox, LeftMarginWidth As Long, _
TopMarginHeight, RightMarginWidth, _
BottomMarginHeight, Prn)
Dim LeftOffset As Long, TopOffset As Long
Dim LeftMargin As Long, TopMargin As Long
Dim RightMargin As Long, BottomMargin As Long
Dim fr As FormatRange
Dim rcDrawTo As Rect
Dim rcPage As Rect
Dim TextLength As Long
Dim NextCharPosition As Long
Dim r As Long
Prn.Print Space( 1 )
Prn.ScaleMode = vbTwips
LeftOffset = Prn.ScaleX(GetDeviceCaps(Prn.hdc, _
PHYSICALOFFSETX), vbPixels, vbTwips)
TopOffset = Prn.ScaleY(GetDeviceCaps(Prn.hdc, _
PHYSICALOFFSETY), vbPixels, vbTwips)
LeftMargin = LeftMarginWidth - LeftOffset
TopMargin = TopMarginHeight - TopOffset
RightMargin = (Prn.Width - RightMarginWidth) - LeftOffset
BottomMargin = (Prn.height - BottomMarginHeight) - TopOffset
rcPage.Left = 0
rcPage.Top = 0
rcPage.Right = Prn.ScaleWidth
rcPage.Bottom = Prn.ScaleHeight
rcDrawTo.Left = LeftMargin
rcDrawTo.Top = TopMargin
rcDrawTo.Right = RightMargin
rcDrawTo.Bottom = BottomMargin
fr.hdc = Prn.hdc ' Use the same DC for measuring and rendering
fr.hdcTarget = Prn.hdc ' Point at printer hDC
fr.rc = rcDrawTo ' Indicate the area on page to drawto
fr.rcPage = rcPage ' Indicate entire size of page
fr.chrg.cpMin = 0 ' Indicate start of text through
fr.chrg.cpMax = - 1 ' end of the text
TextLength = Len(RTF.Text)
Do
NextCharPosition = SendMessage(RTF.hwnd, EM_FORMATRANGE, True, fr)
If NextCharPosition >= TextLength Then Exit Do 'If done thenexit
fr.chrg.cpMin = NextCharPosition ' Starting position for next Page
Prn.NewPage ' Move on to next page
Prn.Print Space( 1 ) ' Re-initialize hDC
fr.hdc = Prn.hdc
fr.hdcTarget = Prn.hdc
Loop
Prn.EndDoc
r = SendMessage(RTF.hwnd, EM_FORMATRANGE, False, ByVal CLng( 0 ))
End Function
'В форму (Печать текста)
sPrinter = "INSTALLED_Printer_NAME"
'Установленый принтер принтер например: \\GMSVB\PRINTER1 (это у меня)
For i = 0 To Printers.Count - 1
If UCase(Printers(i).Port) = UCase(sPrinter) Then
Set Printer = Printers(i)
PrintRichText RichTexBox, 500 , 500 , 500 , 500 , Printer inch. ' В дюймах
Printer.EndDoc
Exit For
End If
Next i
'60. Печать RTF
'#########################
'Одна из проблематичных частей разработки профессиональнальных приложений в Visual Basic, это добавление в программу возможности печати. С появлением Visual Basic 4 у разработчиков появилась возможность пользоваться новым объектом Printer. Однако, у этого объекта есть серьёзнае недостатки, а именно, невозможно узнать готов принтер к печати или занят, вставлена в него бумага или нет и т.д. Поэтому для получения такой информации можно воспользоваться API функцией GetPrinter.
Private Declare Function GetPrinterApi Lib "winspool.drv" Alias _
"GetPrinterA" (ByVal hPrinter As Long, _
ByVal Level As Long, _
buffer As Long, _
ByVal pbSize As Long, _
pbSizeNeeded As Long) As Long
'Используя дескриптор принтера hPrinter она заполняет буфер информацией из драйвера принтера. Чтобы получить дескриптор из объекта Printer, нам необходимо воспользоваться API функцией OpenPrinter.
'Как только мы закончим использовать этот дескриптор, его необходимо освободить при помощи API функции ClosePrinter.
Private Type PRINTER_DEFAULTS
pDatatype As String
pDevMode As DEVMODE
DesiredAccess As Long
End Type
Private Declare Function OpenPrinter Lib "winspool.drv" _
Alias "OpenPrinterA" (ByVal pPrinterName As String, _
phPrinter As Long, pDefault As PRINTER_DEFAULTS) As Long
Private Declare Function ClosePrinter Lib "winspool.drv" _
(ByVal hPrinter As Long) As Long
'А вот как выглядит код получения дескриптора принтера.
Dim lret As Long
Dim pDef As PRINTER_DEFAULTS
lret = OpenPrinter(Printer.DeviceName, mhPrinter, pDef)
' Различные состояния принтера
'
'Драйвер принтера может вернуть различные стандартные состояния принтера.
Public Enum Printer_Status
PRINTER_STATUS_READY = &H0
PRINTER_STATUS_PAUSED = &H1
PRINTER_STATUS_ERROR = &H2
PRINTER_STATUS_PENDING_DELETION = &H4
PRINTER_STATUS_PAPER_JAM = &H8
PRINTER_STATUS_PAPER_OUT = &H10
PRINTER_STATUS_MANUAL_FEED = &H20
PRINTER_STATUS_PAPER_PROBLEM = &H40
PRINTER_STATUS_OFFLINE = &H80
PRINTER_STATUS_IO_ACTIVE = &H100
PRINTER_STATUS_BUSY = &H200
PRINTER_STATUS_PRINTING = &H400
PRINTER_STATUS_OUTPUT_BIN_FULL = &H800
PRINTER_STATUS_NOT_AVAILABLE = &H1000
PRINTER_STATUS_WAITING = &H2000
PRINTER_STATUS_PROCESSING = &H4000
PRINTER_STATUS_INITIALIZING = &H8000
PRINTER_STATUS_WARMING_UP = &H10000
PRINTER_STATUS_TONER_LOW = &H20000
PRINTER_STATUS_NO_TONER = &H40000
PRINTER_STATUS_PAGE_PUNT = &H80000
PRINTER_STATUS_USER_INTERVENTION = &H100000
PRINTER_STATUS_OUT_OF_MEMORY = &H200000
PRINTER_STATUS_DOOR_OPEN = &H400000
PRINTER_STATUS_SERVER_UNKNOWN = &H800000
PRINTER_STATUS_POWER_SAVE = &H1000000
End Enum
'Существуют несколько разных структур данных, которые возвращает драйвер принтера (в Windows 2000, например, их девять штук), однако только две первые являются наиболее универсальными и подходят для всех версий Windows. Из них вторая является наиболее интересной для нас (PRINTER_INFO_2)
Private Type PRINTER_INFO_2
pServerName As String
pPrinterName As String
pShareName As String
pPortName As String
pDriverName As String
pComment As String
pLocation As String
pDevMode As Long
pSepFile As String
pPrintProcessor As String
pDatatype As String
pParameters As String
pSecurityDescriptor As Long
Attributes As Long
Priority As Long
DefaultPriority As Long
StartTime As Long
UntilTime As Long
Status As Long
JobsCount As Long
AveragePPM As Long
End Type
'Однако, не достаточно просто передать эту структуру в API функцию GetPrinter, так как принтер может вернуть больше информации, чем размер структуры. Поэтому, если не зарезервировать достаточного буфера для неё, программа может "выполнить недопустимую оперцию".
'К счастью, сама функция GetPrinter позволяет узнать необходимый объём буфера для структуры. Для этого достаточно передать ноль в параметре pbSize, тогда функция вернёт размер требуемого буфера в pbSizeNeeded.
'Таким образом, получение информации из драйвера принтера состоит из двух этапов:
Dim lret As Long
Dim SizeNeeded As Long
Dim buffer() As Long
ReDim Preserve buffer( 0 To 1 ) As Long
lret = GetPrinterApi(mhPrinter, Index, buffer( 0 ), UBound(buffer), SizeNeeded)
ReDim Preserve buffer( 0 To (SizeNeeded / 4 ) + 3 ) As Long
lret = GetPrinterApi(mhPrinter, Index, buffer( 0 ), UBound(buffer) * 4 , SizeNeeded)
'Однако, мы выделили буфер значений Long, а некоторые значения в структуре PRINTER_INFO_2 имеют тип данных String. Поэтому, необходимо получить эти строковые данные из соответствущих адресов буфера.
'Для получения строки по указанному адресу, используется API функция CopyMemory. Текже существует API функция IsBadStringPtr, которая используется для проверки того, что по указанному адресу содержится допустимая строка.
' Функции работы с памятью
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
' Проверка указателя в StringFromPointer
Private Declare Function IsBadStringPtrByLong Lib "kernel32" Alias "IsBadStringPtrA" (ByVal lpsz As Long, ByVal ucchMax As Long) As Long
'Получение строки по указателю, это обычная вещь, поэтому такую функцию нужно всегда иметь в своём арсенале.
Public Function StringFromPointer(lpString As Long, lMaxLength As Long) As String
Dim sRet As String
Dim lret As Long
If lpString = 0 Then
StringFromPointer = ""
Exit Function
End If
If IsBadStringPtrByLong(lpString, lMaxLength) Then
' Ошибка - данный указатель нельзя использовать
StringFromPointer = ""
Exit Function
End If
' Подготовка к получению строки...
sRet = Space$(lMaxLength)
CopyMemory ByVal sRet, ByVal lpString, ByVal Len(sRet)
If Err.LastDllError = 0 Then
If InStr(sRet, Chr$( 0 )) > 0 Then
sRet = Left$(sRet, InStr(sRet, Chr$( 0 )) - 1 )
End If
End If
StringFromPointer = sRet
End Function
'А теперь используем эту функцию, чтобы заполнить нашу переменную PRINTER_INFO_2:
With mPRINTER_INFO_2 ' Эта переменная типа PRINTER_INFO_2
.pServerName = StringFromPointer(buffer( 0 ), 1024 )
.pPrinterName = StringFromPointer(buffer( 1 ), 1024 )
.pShareName = StringFromPointer(buffer( 2 ), 1024 )
.pPortName = StringFromPointer(buffer( 3 ), 1024 )
.pDriverName = StringFromPointer(buffer( 4 ), 1024 )
.pComment = StringFromPointer(buffer( 5 ), 1024 )
.pLocation = StringFromPointer(buffer( 6 ), 1024 )
.pDevMode = buffer( 7 )
.pSepFile = StringFromPointer(buffer( 8 ), 1024 )
.pPrintProcessor = StringFromPointer(buffer( 9 ), 1024 )
.pDatatype = StringFromPointer(buffer( 10 ), 1024 )
.pParameters = StringFromPointer(buffer( 11 ), 1024 )
.pSecurityDescriptor = buffer( 12 )
.Attributes = buffer( 13 )
.Priority = buffer( 14 )
.DefaultPriority = buffer( 15 )
.StartTime = buffer( 16 )
.UntilTime = buffer( 17 )
.Status = buffer( 18 )
.JobsCount = buffer( 19 )
.AveragePPM = buffer( 20 )
End With
'61. Извлечение иконок
'#########################
'Нам Понадобятся:
Command Button - Command1
TextBox -Text1
PictureBox -Picture1
'А также для удобства брауза файлов CommonDialog - CD1
Option Explicit
Private Declare Function ExtractAssociatedIcon Lib "shell32.dll" Alias _
"ExtractAssociatedIconA" (ByVal hInst As Long, _
ByVal lpIconPath As String, lpiIcon As Long) As Long
Private Declare Function DrawIcon Lib "user32" (ByVal hdc As Long, _
ByVal X As Long, ByVal Y As Long, ByVal hIcon As Long) As Long
Private Declare Function DestroyIcon Lib "user32" _
(ByVal hIcon As Long) As Long
Private Type Rect
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
'Разные Функции
Private Declare Function BitBlt Lib "gdi32" _
(ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, _
ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Const SRCCOPY = &HCC0020
Private Declare Function CreateCompatibleDC Lib "gdi32" _
(ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" _
(ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function SelectObject Lib "gdi32" _
(ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" _
(ByVal hObject As Long) As Long
Private Declare Function OpenClipboard Lib "user32" _
(ByVal hwnd As Long) As Long
Private Declare Function CloseClipboard Lib "user32" _
() As Long
Private Declare Function SetClipboardData Lib "user32" _
(ByVal wFormat As Long, ByVal hMem As Long) As Long
Private Declare Function EmptyClipboard Lib "user32" _
() As Long
Private Const CF_BITMAP = 2
Private Sub Command1_Click()
CD1.ShowOpen 'Открываем Брауз
Text1.Text = CD1.FileName 'Присваеваем Тексту Путь и Имя Файла
Picture1.Cls 'Очищаем Картинку От Старой Иконки
Dim sPath As String, hIcon As Long, nIcon As Long 'Присваеваем Переменные
sPath = Text1.Text 'Берем путь из Текста
'Забираем Верхнюю Иконку
hIcon = ExtractAssociatedIcon(App.hInstance, sPath, nIcon)
DrawIcon Picture1.hdc, 0 &, 0 &, hIcon 'Вставляем иконку в PictureBox
DestroyIcon hIcon 'Берём Иконку
CopyEntirePicture Picture1 'Вставляем иконку в буфер обмена.
'Теперь Можно Вставлять Иконку Хоть Куда
End Sub
'Функция Тута (Копирование Рисунка)
Public Function CopyEntirePicture(ByRef objFrom As Object) As Boolean
Dim lhDC As Long
Dim lhBMP As Long
Dim lhBMPOld As Long
Dim lWidthPixels As Long
Dim lHeightPixels As Long
lhDC = CreateCompatibleDC(objFrom.hdc)
If (lhDC <> 0 ) Then
lWidthPixels = objFrom.ScaleX(objFrom.ScaleWidth, objFrom.ScaleMode, vbPixels)
lHeightPixels = objFrom.ScaleY(objFrom.ScaleHeight, objFrom.ScaleMode, vbPixels)
lhBMP = CreateCompatibleBitmap(objFrom.hdc, lWidthPixels, lHeightPixels)
If (lhBMP <> 0 ) Then
lhBMPOld = SelectObject(lhDC, lhBMP)
BitBlt lhDC, 0 , 0 , lWidthPixels, lHeightPixels, objFrom.hdc, 0 , 0 , SRCCOPY
SelectObject lhDC, lhBMPOld
OpenClipboard 0
EmptyClipboard
SetClipboardData CF_BITMAP, lhBMP
CloseClipboard
End If
DeleteObject lhDC
End If
End Function
'61. смениа системных параметров: десятичный разделитель и разделитель в дате
'#########################
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
LParam As Any) _
As Long
Const WM_WININICHANGE = &H1A
Const HWND_BROADCAST = &HFFFF
' Обычными файловыми операциями ищешь в win.ini (раздел [intl]) строки:
' sDate=.
' sDecimal=.
' Меняешь точки на что надобно, потом запускаешь:
r = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0 , ByVal "windows")
'62. Сохранить картинку в буфере в файл.
'#########################
' Checks the clipboard for a bitmap
' If found, creates a standard Picture object from the
' clipboard contetnts and saves it to a file
' The code requires a reference to the "OLE Automation" type library
' The code in this module has been derived primarily from _
' the PatsePicture sample on Stephen Bullen's Excel Page _
' - http://www.bmsltd.ie/Excel/Default.htm
'Windows API Function Declarations
Private Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Integer) As Long
Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Integer) As Long
Private Declare Function CloseClipboard Lib "user32" () As Long
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle _
As Long, IPic As IPicture) As Long
Private Declare Function CopyImage Lib "user32" (ByVal handle As Long, _
ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, _
ByVal un2 As Long) As Long
'The API format types we need
Const CF_BITMAP = 2
Const IMAGE_BITMAP = 0
Const LR_COPYRETURNORG = &H4
'Declare a UDT to store a GUID for the IPicture OLE Interface
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4( 0 To 7 ) As Byte
End Type
'Declare a UDT to store the bitmap information
Private Type uPicDesc
Size As Long
Type As Long
hPic As Long
hPal As Long
End Type
Public Function Clip2File()
Dim strOutputPath As String, oPic As IPictureDisp
'Get the filename to save the bitmap to
strOutputPath = Environ("TEMP") & "\temp.bmp"
'Retrieve the picture from the clipboard...
Set oPic = GetClipPicture()
'... and save it to the file
If Not oPic Is Nothing Then
SavePicture oPic, strOutputPath
Clip2File = strOutputPath
Else
Clip2File = ""
MsgBox "Unable to retrieve bitmap from clipboard"
End If
End Function
Function GetClipPicture() As IPicture
Dim h As Long, hPicAvail As Long, hPtr As Long, _
hPal As Long, hCopy As Long
'Check if the clipboard contains a bitmap
hPicAvail = IsClipboardFormatAvailable(CF_BITMAP)
If hPicAvail <> 0 Then
'Get access to the clipboard
h = OpenClipboard( 0 &)
If h > 0 Then
'Get a handle to the image data
hPtr = GetClipboardData(CF_BITMAP)
hCopy = CopyImage(hPtr, IMAGE_BITMAP, 0 , 0 , LR_COPYRETURNORG)
'Release the clipboard to other programs
h = CloseClipboard
'If we got a handle to the image, convert it into _
'a Picture object and return it
If hPtr <> 0 Then Set GetClipPicture = CreatePicture(hCopy, _
0 , CF_BITMAP)
End If
End If
End Function
Private Function CreatePicture(ByVal hPic As Long, ByVal hPal As Long, _
ByVal lPicType) As IPicture
' IPicture requires a reference to "OLE Automation"
Dim r As Long, uPicInfo As uPicDesc, IID_IDispatch As GUID, _
IPic As IPicture
'OLE Picture types
Const PICTYPE_BITMAP = 1
' Create the Interface GUID (for the IPicture interface)
With IID_IDispatch
.Data1 = &H7BF80980
.Data2 = &HBF32
.Data3 = &H101A
.Data4( 0 ) = &H8B
.Data4( 1 ) = &HBB
.Data4( 2 ) = &H0
.Data4( 3 ) = &HAA
.Data4( 4 ) = &H0
.Data4( 5 ) = &H30
.Data4( 6 ) = &HC
.Data4( 7 ) = &HAB
End With
' Fill uPicInfo with necessary parts.
With uPicInfo
.Size = Len(uPicInfo) ' Length of structure.
.Type = PICTYPE_BITMAP ' Type of Picture
.hPic = hPic ' Handle to image.
.hPal = 0 ' Handle to palette (if bitmap).
End With
' Create the Picture object.
r = OleCreatePictureIndirect(uPicInfo, IID_IDispatch, True, IPic)
' Return the new Picture object.
Set CreatePicture = IPic
End Function