powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Использование функций WinAPI в Access
25 сообщений из 39, страница 1 из 2
Использование функций WinAPI в Access
    #37318302
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
не стал делать для каждой функции спойлер - оч долго - всё для 32 бит!
Код: plaintext
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


можт у кого есть почитать как из 32 передекларировать в 64 бит!
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318309
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Респект.
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318314
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WRX,

Богато, богато.
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318321
полином
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
Function SetPapent

очень узнаваемый паттерн
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318323
не всё применимо для VBA, часть кода использует объекты VB.
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318324
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
понятное дело, что это лишь часть большого айсберга...прошу у кого есть инфа по данной тематике - не стесняйтесь - делитесь с аудиторией :))
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318331
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WRX,

Для этого надо хотябы просмотреть.
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318338
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
Эффект прозрачности
Код: plaintext
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.
'Win API позволяющая задать прозрачность окна
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long

Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hwnd As Long, _
ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long


Private Const LWA_COLORKEY = &H1
Private Const LWA_ALPHA = &H2
Private Const GWL_EXSTYLE = (- 20 )
Private Const WS_EX_LAYERED = &H80000

' Layered - степень прозрачности 0-255
' Примечание: форма должна быть всплывающей
Public Sub TransparentForm(hwnd As Long, Layered As Byte)
    Dim ret As Long
    ret = GetWindowLong(hwnd, GWL_EXSTYLE)
    ret = ret Or WS_EX_LAYERED
    SetWindowLong hwnd, GWL_EXSTYLE, ret
    SetLayeredWindowAttributes hwnd,  0 , Layered, LWA_ALPHA
End Sub
'вызывается
TransparentForm Me.hwnd,  230 
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318376
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
справочник по WinAPI
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318982
Фотография Старый ворчун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полином
Код: plaintext
Function SetPapent

очень узнаваемый паттерн

:)

Наверное отсюда
8 Замораживаем Виндов ?
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37318997
полином
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Старый ворчунНаверное отсюда

:)

вообще книжка была такая (ни айбиэсэн ни тираж уже совсем не помню :) )
с такой именно опечаткой -она и запомнилась :) старая книжка.
точно запомнилось именно "Папент" это почти как Parent, но понятнее :)
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37319622
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
продолжение

Код: plaintext
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.
' Win API "Открытие файла в его родном приложении" (привет от Hiprog (точно не помню))
' #################################

Public 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_SHOWMAXIMIZED =  3 
Public Const SW_SHOWDEFAULT =  10 
Public Const SW_SHOWNOACTIVATE =  4 
Public Const SW_SHOWNORMAL =  1 


Function StartOfFile(strNameFile As String)
    Dim intResult As Integer
    Dim vTaskID
    intResult = ShellExecute(Application.hWndAccessApp, "open", strNameFile,  0 ,  0 , SW_SHOWNORMAL)
        If intResult =  31  Then
'            Select Case MsgBox("     Файл с таким расширением не зарегистрирован!" _
'                    & Chr(13) & "Желаете открыть его выбрав самостоятельно программу?" _
'                    & vbCrLf & _
'                        "", vbYesNo + vbExclamation, "ВНИМАНИЕ")
'                    Case vbNo
'                        Exit Sub
'                    Case vbYes
'                        GoTo calc
'                    End Select
'calc:
            vTaskID = Shell("rundll32.exe shell32.dll, OpenAs_RunDLL strNameFile", vbNormalFocus) ' Вызов окна выбора программы для открытия файла с незарегистированным расширением
        End If
End Function


' Win API "команда свернуть"
' #################################

Private Declare Function apiShowWindow Lib "user32" _
 Alias "ShowWindow" (ByVal hwnd As Long, _
 ByVal nCmdShow As Long) As Long
Public Const SW_HIDE =  0 
Public Const SW_SHOWNORMAL =  1 
Public Const SW_SHOWMINIMIZED =  2 
Public Const SW_MAXIMIZE =  3 
Public Const SW_SHOWMAXIMIZED =  3 
Public Const SW_SHOWNOACTIVATE =  4 
Public Const SW_SHOW =  5 
Public Const SW_MINIMIZE =  6 
Public Const SW_SHOWMINNOACTIVE =  7 
Public Const SW_SHOWNA =  8 
Public Const SW_RESTORE =  9 
Public Const SW_SHOWDEFAULT =  10 

Public s As Date

Function min() ' Функция сворачивания
    
    Dim loX  As Long
    nCmdShow = SW_SHOWMINNOACTIVE
    loX = apiShowWindow(hWndAccessApp, nCmdShow)

End Function

Function max() ' Функция разворачивания
    Dim loX  As Long
    Dim nCmdShow As Long
      nCmdShow = SW_SHOWMAXIMIZED
      loX = apiShowWindow(hWndAccessApp, nCmdShow)
End Function

'Вызов

    Call min
    Call max


' Win API "конвертация SNP в PDF" (привет от Лебанса) (2 библиотеки должны располагаться либо в текущей директории БД либо в windows\system32)
'(сохранение PDF происходит по умолчанию в "Мои документы")
' #################################

' ******************************************************
#Const ConDebug =  0     ' Set to 1 to force loading of DEBUG StrStorage.DLL
#If (ConDebug =  1 ) Then

' This is where I screwed up the Font Embedding. Forgot to declare PDFNoFontEmbedding as ByVal!
    Public Declare Function ConvertUncompressedSnapshot Lib "C:\VisualCsource\Debug\StrStorage.dll" _
    (ByVal UnCompressedSnapShotName As String, _
    ByVal OutputPDFname As String, _
    Optional ByVal CompressionLevel As Long =  0 , _
    Optional ByVal PasswordOpen As String = "", _
    Optional ByVal PasswordOwner As String = "", _
    Optional ByVal PasswordRestrictions As Long =  0 , _
    Optional ByVal PDFNoFontEmbedding As Long =  0 , _
    Optional ByVal PDFUnicodeFlags As Long =  0  _
    ) As Boolean


    Public Declare Function DrawTableWindow Lib "C:\VisualCsource\Debug\StrStorage.dll" _
    (ByVal TableName As String, _
    ByVal Fields As String, _
    ByVal NumFields As Long, _
    ByVal Xpos As Double, _
    ByVal Ypos As Double, _
    ByVal Width As Double, _
    ByVal Height As Double _
    ) As Long

    Public Declare Function DrawLine Lib "C:\VisualCsource\Debug\StrStorage.dll" _
    (ByVal Width As Double, _
    ByVal Width1 As Double, _
    ByVal Xpos As Double, _
    ByVal Ypos As Double, _
    ByVal Xpos1 As Double, _
    ByVal Ypos1 As Double, _
    ByVal Attrib As Long _
    ) As Long


    Public Declare Function BeginPDF Lib "C:\VisualCsource\Debug\StrStorage.dll" _
    (ByVal PDFfilename As String, _
    ByVal PageWidth As Long, _
    ByVal PageHeight As Long _
    ) As Long

    Public Declare Function EndPDF Lib "C:\VisualCsource\Debug\StrStorage.dll" _
    () As Long

    Public Declare Function MergePDFDocuments Lib "C:\VisualCsource\Debug\StrStorage.dll" _
    (ByVal PDFMaster As String, _
    ByVal PDFChild As String _
    ) As Boolean

#Else

' This is where I screwed up the Font Embedding. Forgot to declare PDFNoFontEmbedding as ByVal!
Public Declare Function ConvertUncompressedSnapshot Lib "StrStorage.dll" _
    (ByVal UnCompressedSnapShotName As String, _
    ByVal OutputPDFname As String, _
    Optional ByVal CompressionLevel As Long =  0 , _
    Optional ByVal PasswordOpen As String = "", _
    Optional ByVal PasswordOwner As String = "", _
    Optional ByVal PasswordRestrictions As Long =  0 , _
    Optional ByVal PDFNoFontEmbedding As Long =  0 , _
    Optional ByVal PDFUnicodeFlags As Long =  0  _
    ) As Boolean
    
    
    Public Declare Function DrawTableWindow Lib "StrStorage.dll" _
    (ByVal TableName As String, _
    ByVal Fields As String, _
    ByVal NumFields As Long, _
    ByVal Xpos As Double, _
    ByVal Ypos As Double, _
    ByVal Width As Double, _
    ByVal Height As Double _
    ) As Long
    
    Public Declare Function DrawLine Lib "StrStorage.dll" _
    (ByVal Width As Double, _
    ByVal Width1 As Double, _
    ByVal Xpos As Double, _
    ByVal Ypos As Double, _
    ByVal Xpos1 As Double, _
    ByVal Ypos1 As Double, _
    ByVal Attrib As Long _
    ) As Long
    
    
    Public Declare Function BeginPDF Lib "StrStorage.dll" _
    (ByVal PDFfilename As String, _
    ByVal PageWidth As Long, _
    ByVal PageHeight As Long _
    ) As Long
    
    Public Declare Function EndPDF Lib "StrStorage.dll" _
    () As Long
    
    Public Declare Function MergePDFDocuments Lib "StrStorage.dll" _
    (ByVal PDFMaster As String, _
    ByVal PDFChild As String _
    ) As Boolean
    

#End If

' For debugging with Visual C++
'Lib "C:\VisualCsource\Debug\StrStorage.dll"

Private Declare Function ShellExecuteA Lib "shell32.dll" _
(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 Declare Function LoadLibrary Lib "kernel32" _
Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long

Private Declare Function FreeLibrary Lib "kernel32" _
(ByVal hLibModule As Long) As Long

Private Declare Function GetTempPath Lib "kernel32" _
Alias "GetTempPathA" (ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long

Private Declare Function GetTempFileName _
Lib "kernel32" Alias "GetTempFileNameA" _
(ByVal lpszPath As String, _
ByVal lpPrefixString As String, _
ByVal wUnique As Long, _
ByVal lpTempFileName As String) As Long
 
Private Declare Function SetupDecompressOrCopyFile _
Lib "setupAPI" _
Alias "SetupDecompressOrCopyFileA" ( _
ByVal SourceFileName As String, _
ByVal TargetFileName As String, _
ByVal CompressionType As Integer) As Long

Private Declare Function SetupGetFileCompressionInfo _
Lib "setupAPI" _
Alias "SetupGetFileCompressionInfoA" ( _
ByVal SourceFileName As String, _
TargetFileName As String, _
SourceFileSize As Long, _
DestinationFileSize As Long, _
CompressionType As Integer _
) As Long

 
'Compression types
Private Const FILE_COMPRESSION_NONE =  0 
Private Const FILE_COMPRESSION_WINLZA =  1 
Private Const FILE_COMPRESSION_MSZIP =  2 

Private Const Pathlen =  256 
Private Const MaxPath =  256 

'Enum TKeyLen
   Public Const kl40bit =  0     '  40 bit RC4 encryption (Acrobat 3 or higher)
   Public Const kl128bit =  1  ' 128 bit RC4 encryption (Acrobat 5 or higher)
   Public Const kl128bitEx =  2  ' 128 bit RC4 encryption (Acrobat 6 or higher)
'End Enum

'Enum TRestrictions
  Public Const rsDenyNothing =  0 
  Public Const rsDenyAll =  3900 
  Public Const rsPrint =  4 
  Public Const rsModify =  8 
  Public Const rsCopyObj =  16 
  Public Const rsAddObj =  32 
  ' 128 bit encryption only -> these values are ignored if 40 bit encryption is used
  Public Const rsFillInFormFields =  256 
  Public Const rsExtractObj =  512 
  Public Const rsAssemble =  1024 
  Public Const rsPrintHighRes =  2048 
  Public Const rsExlMetadata =  4096       ' PDF 1.5 -> can be used with kl128bitEx only
'End Enum



Public Type POINTAPI
   x As Long
   y As Long
End Type

Public Type RECTL
   Left As Long
   Top As Long
   Right As Long
   Bottom As Long
End Type


Public Const AAAlength =  12 
Public Const FFFlength =  8 
Public Const Padding =  12 
Public Const NameLengthMax =  128 
' 64 Char MAX for a DAO Table Name * 2 = Unicode

Public Type RelBlob
    Sig As Long
    AAAs( 1  To AAAlength) As Byte
    RelWinX1  As Long
    RelWinY1 As Long
    RelWinX2  As Long
    RelWinY2 As Long
    Blank As Long
    FFFs( 1  To FFFlength) As Byte
    ClientRectX As Long
    ClientRectY As Long
    ScrollBarYoffset As Long
    ScrollBarXoffset As Long
    Pad1 As Long
    NumWindows As Long
End Type

Public Type RelWindow
    RelWinX1  As Long
    RelWinY1 As Long
    RelWinX2  As Long
    RelWinY2 As Long
    Junk As Long
    WinName As String * NameLengthMax
    Junk1 As Long
    WinNameMaster As String * NameLengthMax
    'Pad(1 To Padding) As Byte
    Junk2 As Long
End Type

Public Type RelWindowMin
    RelWinX1  As Long
    RelWinY1 As Long
    RelWinX2  As Long
    RelWinY2 As Long
    Column As Long
    WinName As String
End Type

Public Declare Function ScreenToClient Lib "user32" _
(ByVal hwnd As Long, lpPoint As POINTAPI) As Long

Public 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

Public Declare Function apiGetWindow Lib "user32" _
Alias "GetWindow" (ByVal hwnd As Long, ByVal wCmd As Long) As Long

Public Declare Function GetWindowRect Lib "user32" _
(ByVal hwnd As Long, lpRect As RECTL) As Long

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 Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Public Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)

' Create an Information Context
Private Declare Function apiCreateIC Lib "gdi32" Alias "CreateICA" _
(ByVal lpDriverName As String, ByVal lpDeviceName As String, _
ByVal lpOutput As String, lpInitData As Any) As Long

Private Declare Function apiGetDeviceCaps Lib "gdi32" _
Alias "GetDeviceCaps" (ByVal hdc As Long, ByVal nIndex As Long) As Long


Private Declare Function apiDeleteDC Lib "gdi32" _
  Alias "DeleteDC" (ByVal hdc As Long) As Long


' SetWindowPos() Constants
Public Const SWP_SHOWWINDOW = &H40

' GetWindow() Constants
Public Const GW_HWNDNEXT =  2 
Public Const GW_CHILD =  5 

'  Device Parameters for GetDeviceCaps()
Private Const LOGPIXELSX =  88         '  Logical pixels/inch in X
Private Const LOGPIXELSY =  90         '  Logical pixels/inch in Y

' ***********************************************
'       Font, DC and TextWidth stuff

Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type
 
Private Const LF_FACESIZE =  32 
 
Private Type LOGFONT
        lfHeight As Long
        lfWidth As Long
        lfEscapement As Long
        lfOrientation As Long
        lfWeight As Long
        lfItalic As Byte
        lfUnderline As Byte
        lfStrikeOut As Byte
        lfCharSet As Byte
        lfOutPrecision As Byte
        lfClipPrecision As Byte
        lfQuality As Byte
        lfPitchAndFamily As Byte
        lfFaceName As String * LF_FACESIZE
End Type

Private Type TEXTMETRIC
        tmHeight As Long
        tmAscent As Long
        tmDescent As Long
        tmInternalLeading As Long
        tmExternalLeading As Long
        tmAveCharWidth As Long
        tmMaxCharWidth As Long
        tmWeight As Long
        tmOverhang As Long
        tmDigitizedAspectX As Long
        tmDigitizedAspectY As Long
        tmFirstChar As Byte
        tmLastChar As Byte
        tmDefaultChar As Byte
        tmBreakChar As Byte
        tmItalic As Byte
        tmUnderlined As Byte
        tmStruckOut As Byte
        tmPitchAndFamily As Byte
        tmCharSet As Byte
End Type

Private Declare Function GetTextMetrics Lib "gdi32" Alias "GetTextMetricsA" _
(ByVal hdc As Long, lpMetrics As TEXTMETRIC) As Long
 
Private Declare Function apiCreateFontIndirect Lib "gdi32" Alias _
        "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long
 
Private Declare Function apiSelectObject Lib "gdi32" Alias "SelectObject" _
(ByVal hdc As Long, _
ByVal hObject As Long) As Long
 
Private Declare Function apiDeleteObject Lib "gdi32" _
  Alias "DeleteObject" (ByVal hObject As Long) As Long
 
Private Declare Function apiMulDiv Lib "kernel32" Alias "MulDiv" _
(ByVal nNumber As Long, _
ByVal nNumerator As Long, ByVal nDenominator As Long) As Long
 
Private Declare Function apiGetDC Lib "user32" _
  Alias "GetDC" (ByVal hwnd As Long) As Long
 
Private Declare Function apiReleaseDC Lib "user32" _
 Alias "ReleaseDC" (ByVal hwnd As Long, _
 ByVal hdc As Long) As Long
  
Private Declare Function apiDrawText Lib "user32" Alias "DrawTextA" _
(ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, _
lpRect As RECT, ByVal wFormat As Long) As Long

Private Declare Function CreateDCbyNum Lib "gdi32" Alias "CreateDCA" _
(ByVal lpDriverName As String, ByVal lpDeviceName As String, _
ByVal lpOutput As Long, ByVal lpInitData As Long) As Long  'DEVMODE) As Long

  
Declare Function GetProfileString Lib "kernel32" _
   Alias "GetProfileStringA" _
  (ByVal lpAppName As String, _
   ByVal lpKeyName As String, _
   ByVal lpDefault As String, _
   ByVal lpReturnedString As String, _
   ByVal nSize As Long) As Long

' CONSTANTS
Private Const TWIPSPERINCH =  1440 

' DrawText() Format Flags
Private Const DT_TOP = &H0
Private Const DT_LEFT = &H0
Private Const DT_CALCRECT = &H400
Private Const DT_WORDBREAK = &H10
Private Const DT_EXTERNALLEADING = &H200
Private Const DT_EDITCONTROL = &H2000&
Private Const DT_NOCLIP = &H100

' Font stuff
Private Const OUT_DEFAULT_PRECIS =  0 
Private Const OUT_STRING_PRECIS =  1 
Private Const OUT_CHARACTER_PRECIS =  2 
Private Const OUT_STROKE_PRECIS =  3 
Private Const OUT_TT_PRECIS =  4 
Private Const OUT_DEVICE_PRECIS =  5 
Private Const OUT_RASTER_PRECIS =  6 
Private Const OUT_TT_ONLY_PRECIS =  7 
Private Const OUT_OUTLINE_PRECIS =  8 

Private Const CLIP_DEFAULT_PRECIS =  0 
Private Const CLIP_CHARACTER_PRECIS =  1 
Private Const CLIP_STROKE_PRECIS =  2 
Private Const CLIP_MASK = &HF
Private Const CLIP_LH_ANGLES =  16 
Private Const CLIP_TT_ALWAYS =  32 
Private Const CLIP_EMBEDDED =  128 

Private Const DEFAULT_QUALITY =  0 
Private Const DRAFT_QUALITY =  1 
Private Const PROOF_QUALITY =  2 

Private Const DEFAULT_PITCH =  0 
Private Const FIXED_PITCH =  1 
Private Const VARIABLE_PITCH =  2 

Private Const ANSI_CHARSET =  0 
Private Const DEFAULT_CHARSET =  1 
Private Const SYMBOL_CHARSET =  2 
Private Const SHIFTJIS_CHARSET =  128 
Private Const HANGEUL_CHARSET =  129 
Private Const CHINESEBIG5_CHARSET =  136 
Private Const OEM_CHARSET =  255 

' ***********************************************

Private mSaveFileName As String

' Full path and name of uncompressed SnapShot file
Private mUncompressedSnapFile As String

' Name of the Report we ' working with
Private mReportName As String

' Instance returned from LoadLibrary calls
Private hLibDynaPDF As Long
Private hLibStrStorage As Long


Public Function ConvertReportToPDF( _
Optional RptName As String = "", _
Optional SnapshotName As String = "", _
Optional OutputPDFname As String = "", _
Optional ShowSaveFileDialog As Boolean = False, _
Optional StartPDFViewer As Boolean = True, _
Optional CompressionLevel As Long =  0 , _
Optional PasswordOpen As String = "", _
Optional PasswordOwner As String = "", _
Optional PasswordRestrictions As Long =  0 , _
Optional PDFNoFontEmbedding As Long =  0 , _
Optional PDFUnicodeFlags As Long =  0  _
) As Boolean

Dim s As String
Dim blRet As Boolean
' Let's see if the DynaPDF.DLL is available.
blRet = LoadLib()
If blRet = False Then
    ' Cannot find DynaPDF.dll or StrStorage.dll file
    Exit Function
End If

On Error GoTo ERR_CREATSNAP

Dim strPath  As String
Dim strPathandFileName  As String
Dim strEMFUncompressed As String

Dim sOutFile As String
Dim lngRet As Long

' Init our string buffer
strPath = Space(Pathlen)

'Save the ReportName to a local var
mReportName = RptName

' Let's kill any existing Temp SnapShot file
    If Len(mUncompressedSnapFile & vbNullString) >  0  Then
        Kill mUncompressedSnapFile
        mUncompressedSnapFile = ""
    End If

' If we have been passed the name of a Snapshot file then
' skip the Snapshot creation process below
        If Len(SnapshotName & vbNullString) =  0  Then
              
            ' Make sure we were passed a ReportName
            If Len(RptName & vbNullString) =  0  Then
                ' No valid parameters - FAIL AND EXIT!!
                ConvertReportToPDF = ""
                Exit Function
            End If
                
            ' Get the Systems Temp path
            ' Returns Length of path(num characters in path)
            lngRet = GetTempPath(Pathlen, strPath)
            ' Chop off NULLS and trailing "\"
            strPath = Left(strPath, lngRet) & Chr( 0 )
            
            ' Now need a unique Filename
            ' locked from a previous aborted attemp.
            ' Needs more work!
            strPathandFileName = GetUniqueFilename(strPath, "SNP" & Chr( 0 ), "snp")
            
            ' Export the selected Report to SnapShot format
            DoCmd.OutputTo acOutputReport, RptName, "SnapshotFormat(*.snp)", _
               strPathandFileName
            ' Make sure the process has time to complete
            DoEvents
        
        Else
            strPathandFileName = SnapshotName
         
        End If

' Let's decompress into same filename but change type to ".tmp"
'strEMFUncompressed = Mid(strPathandFileName, 1, Len(strPathandFileName) - 3)
'strEMFUncompressed = strEMFUncompressed & "tmp"
    Dim sPath As String *  512 
    lngRet = GetTempPath( 512 , sPath)

    strEMFUncompressed = GetUniqueFilename(sPath, "SNP", "tmp")
    
    lngRet = SetupDecompressOrCopyFile(strPathandFileName, strEMFUncompressed,  0 &)

        If lngRet <>  0  Then
            Err.Raise vbObjectError +  525 , "ConvertReportToPDF.SetupDecompressOrCopyFile", _
            "Sorry...cannot Decompress SnapShot File" & vbCrLf & _
            "Please select a different Report to Export"
        End If

' Set our uncompressed SnapShot file name var
    mUncompressedSnapFile = strEMFUncompressed

' Remember to Cleanup our Temp SnapShot File if we were NOT passed the
' Snapshot file as the optional param
            If Len(SnapshotName & vbNullString) =  0  Then
                Kill strPathandFileName
            End If

                If ShowSaveFileDialog = False Then
                
                    ' let's decompress into same filename but change type to ".tmp"
                    ' But first let's see if we were passed an output PDF file name
                    If Len(OutputPDFname & vbNullString) =  0  Then
                        sOutFile = Mid(strPathandFileName,  1 , Len(strPathandFileName) -  3 )
                        sOutFile = sOutFile & "PDF"
                    Else
                        sOutFile = OutputPDFname
                    End If
                
                Else
                    ' Call File Save Dialog
                    sOutFile = fFileDialog()
                    If Len(sOutFile & vbNullString) =  0  Then
                        Exit Function
                    End If
                
                End If

' Call our function in the StrStorage DLL
' Note the Compression and Password params are not hooked up yet.
        blRet = ConvertUncompressedSnapshot(mUncompressedSnapFile, sOutFile, _
        CompressionLevel, PasswordOpen, PasswordOwner, PasswordRestrictions, PDFNoFontEmbedding, PDFUnicodeFlags)

            If blRet = False Then
            Err.Raise vbObjectError +  526 , "ConvertReportToPDF.ConvertUncompressedSnaphot", _
                "Sorry...damaged SnapShot File" & vbCrLf & _
                "Please select a different Report to Export"
            End If

' Do we open new PDF in registered PDF viewer on this system?
                If StartPDFViewer = True Then
                 ShellExecuteA Application.hWndAccessApp, "open", sOutFile, vbNullString, vbNullString,  1 
                End If

' Success
        ConvertReportToPDF = True
        
EXIT_CREATESNAP:

' Let's kill any existing Temp SnapShot file
'If Len(mUncompressedSnapFile & vbNullString) > 0 Then
     On Error Resume Next
   Kill mUncompressedSnapFile
    mUncompressedSnapFile = ""
'End If

' If we aready loaded then free the library
        If hLibStrStorage <>  0  Then
            hLibStrStorage = FreeLibrary(hLibStrStorage)
        End If

            If hLibDynaPDF <>  0  Then
                hLibDynaPDF = FreeLibrary(hLibDynaPDF)
            End If

Exit Function

ERR_CREATSNAP:
MsgBox Err.Description, vbOKOnly, Err.Source & ":" & Err.Number
mUncompressedSnapFile = ""
ConvertReportToPDF = False
Resume EXIT_CREATESNAP

End Function

Private Function LoadLib() As Boolean
    Dim s As String
    Dim blRet As Boolean

On Error Resume Next

    LoadLib = False

' If we aready loaded then free the library
        If hLibDynaPDF <>  0  Then
            hLibDynaPDF = FreeLibrary(hLibDynaPDF)
        End If


' Our error string
    s = "Sorry...cannot find the DynaPDF.dll file" & vbCrLf
    s = s & "Please copy the DynaPDF.dll file into the same folder as this Access MDB or your Windows System32 folder."

' OK Try to load the DLL assuming it is in the same folder as this MDB.
' CurrentDB works with both A97 and A2K or higher
    hLibDynaPDF = LoadLibrary(CurrentDBDir() & "DynaPDF.dll")
    
        If hLibDynaPDF =  0  Then
            ' OK Try to load the DLL assuming it is in the Window System folder
            hLibDynaPDF = LoadLibrary("DynaPDF.dll")
        End If

            If hLibDynaPDF =  0  Then
                MsgBox s, vbOKOnly, "MISSING DynaPDF.dll FILE"
                LoadLib = False
                Exit Function
            End If



'' ** Commented out for Debugging only - Must be active
'' ***************************************************************************
'
' Load StrStorage.DLL
' If we aready loaded then free the library
    If hLibStrStorage <>  0  Then
        hLibStrStorage = FreeLibrary(hLibStrStorage)
    End If

' Our error string
        s = "Sorry...cannot find the StrStorage.dll file" & vbCrLf
        s = s & "Please copy the StrStorage.dll file into the same folder as this Access MDB or your Windows System32 folder."

' OK Try to load the DLL assuming it is in the same folder as this MDB.
' CurrentDB works with both A97 and A2K or higher
        hLibStrStorage = LoadLibrary(CurrentDBDir() & "StrStorage.dll")

            If hLibStrStorage =  0  Then
                ' OK Try to load the DLL assuming it is in the Window System folder
                hLibStrStorage = LoadLibrary("StrStorage.dll")
            End If

                If hLibStrStorage =  0  Then
                    MsgBox s, vbOKOnly, "MISSING StrStorage.dll FILE"
                    LoadLib = False
                    Exit Function
                End If

' RETURN SUCCESS
    LoadLib = True

End Function

'******************** Code Begin ****************
'Code courtesy of
'Terry Kreft & Ken Getz
'
Private Function CurrentDBDir() As String
Dim strDBPath As String
Dim strDBFile As String
    strDBPath = CurrentDb.name
    strDBFile = Dir(strDBPath)
    CurrentDBDir = Left$(strDBPath, Len(strDBPath) - Len(strDBFile))
End Function
'******************** Code End ****************

Private Function GetUniqueFilename(Optional path As String = "", _
Optional Prefix As String = "", _
Optional UseExtension As String = "") _
As String

  Dim wUnique As Long
  Dim lpTempFileName As String
  Dim lngRet As Long

  wUnique =  0 
  If path = "" Then path = CurDir
  lpTempFileName = String(MaxPath,  0 )
  lngRet = GetTempFileName(path, Prefix, _
                            wUnique, lpTempFileName)

  lpTempFileName = Left(lpTempFileName, _
                        InStr(lpTempFileName, Chr( 0 )) -  1 )
  Call Kill(lpTempFileName)
    If Len(UseExtension) >  0  Then
      lpTempFileName = Left(lpTempFileName, Len(lpTempFileName) -  3 ) & UseExtension
    End If
  GetUniqueFilename = lpTempFileName
End Function

Private Function fFileDialog() As String
' Calls the API File Save Dialog Window
' Returns full path to new File

On Error GoTo Err_fFileDialog

' Call the File Common Dialog Window
    Dim clsDialog As Object
    Dim strTemp As String
    Dim strFname As String

    Set clsDialog = New clsCommonDialog

' Fill in our structure
' I'll leave in how to select Gif and Jpeg to
' show you how to build the Filter in case you want
' to use this code in another project.
    clsDialog.Filter = "PDF (*.PDF)" & Chr$( 0 ) & "*.PDF" & Chr$( 0 )
'clsDialog.Filter = clsDialog.Filter & "Gif (*.GIF)" & Chr$(0) & "*.GIF" & Chr$(0)
'clsDialog.Filter = "ALL (*.*)" & Chr$(0) & "*.*" & Chr$(0)
    clsDialog.hdc =  0 
    clsDialog.MaxFileSize =  256 
    clsDialog.max =  256 
    clsDialog.FileTitle = vbNullString
    clsDialog.DialogTitle = "Please Select a path and Enter a Name for the PDF File"
    clsDialog.InitDir = vbNullString
    clsDialog.DefaultExt = vbNullString

' Display the File Dialog
    clsDialog.ShowSave

' See if user clicked Cancel or even selected
' the very same file already selected
    strFname = clsDialog.FileName
'If Len(strFname & vbNullString) = 0 Then
' Raise the exception
 ' Err.Raise vbObjectError + 513, "clsPrintToFit.fFileDialog", _
  '"Please type in a Name for a New File"
'End If

' Return File Path and Name
    fFileDialog = strFname

Exit_fFileDialog:

Err.Clear
Set clsDialog = Nothing
Exit Function

Err_fFileDialog:
fFileDialog = ""
MsgBox Err.Description, vbOKOnly, Err.Source & ":" & Err.Number
Resume Exit_fFileDialog

End Function

Public Function fFileDialogSnapshot() As String
' Calls the API File Open Dialog Window
' Returns full path to existing Snapshot File

On Error GoTo Err_fFileDialog

' Call the File Common Dialog Window
Dim clsDialog As Object
Dim strTemp As String
Dim strFname As String

    Set clsDialog = New clsCommonDialog

    clsDialog.Filter = "SNAPSHOT (*.SNP)" & Chr$( 0 ) & "*.SNP" & Chr$( 0 )
'clsDialog.Filter = "ALL (*.*)" & Chr$(0) & "*.*" & Chr$(0)
    clsDialog.hdc =  0 
    clsDialog.MaxFileSize =  256 
    clsDialog.max =  256 
    clsDialog.FileTitle = vbNullString
    clsDialog.DialogTitle = "Please Select a Snapshot File"
    clsDialog.InitDir = vbNullString
    clsDialog.DefaultExt = vbNullString

' Display the File Dialog
    clsDialog.ShowOpen

' See if user clicked Cancel or even selected
' the very same file already selected
    strFname = clsDialog.FileName
        If Len(strFname & vbNullString) =  0  Then
' Do nothing. Add your desired error logic here.
        End If

' Return File Path and Name
    fFileDialogSnapshot = strFname

Exit_fFileDialog:

Err.Clear
Set clsDialog = Nothing
Exit Function

Err_fFileDialog:
fFileDialogSnapshot = ""
MsgBox Err.Description, vbOKOnly, Err.Source & ":" & Err.Number
Resume Exit_fFileDialog

End Function

Public Function fFileDialogSavePDFname() As String
' Calls the API File Open Dialog Window
' Returns full path to existing Snapshot File

On Error GoTo Err_fFileDialog

' Call the File Common Dialog Window
    Dim clsDialog As Object
    Dim strTemp As String
    Dim strFname As String

    Set clsDialog = New clsCommonDialog
    
    clsDialog.Filter = "PDF (*.PDF)" & Chr$( 0 ) & "*.PDF" & Chr$( 0 )
'clsDialog.Filter = "ALL (*.*)" & Chr$(0) & "*.*" & Chr$(0)
    clsDialog.hdc =  0 
    clsDialog.MaxFileSize =  256 
    clsDialog.max =  256 
    clsDialog.FileTitle = vbNullString
    clsDialog.DialogTitle = "Please Select a name for the PDF File"
    clsDialog.InitDir = vbNullString
    clsDialog.DefaultExt = vbNullString

' Display the File Dialog
    clsDialog.ShowOpen

' See if user clicked Cancel or even selected
' the very same file already selected
    strFname = clsDialog.FileName
        If Len(strFname & vbNullString) =  0  Then
' Do nothing. Add your desired error logic here.
        End If

' Return File Path and Name
fFileDialogSavePDFname = strFname

Exit_fFileDialog:

Err.Clear
Set clsDialog = Nothing
Exit Function

Err_fFileDialog:
fFileDialogSavePDFname = ""
MsgBox Err.Description, vbOKOnly, Err.Source & ":" & Err.Number
Resume Exit_fFileDialog

End Function

Sub ForeignNameX()

   Dim dbsNorthwind As Database
   Dim relLoop As Relation

   Set dbsNorthwind = CurrentDb() 'OpenDatabase("Northwind.mdb")

   Debug.Print "Relation"
   Debug.Print "        Table - Field"
   Debug.Print "  Primary (One) ";
   Debug.Print ".Table - .Fields(0).Name"
   Debug.Print "  Foreign (Many)  ";
   Debug.Print ".ForeignTable - .Fields(0).ForeignName"

   For Each relLoop In dbsNorthwind.Relations
      With relLoop
         Debug.Print
         Debug.Print .name & " Relation"
         Debug.Print "        Table - Field"
         Debug.Print "  Primary (One) ";
         Debug.Print .Table & " - " & .Fields( 0 ).name
         Debug.Print "  Foreign (Many)  ";
         Debug.Print .ForeignTable & " - " & _
            .Fields( 0 ).ForeignName
      End With
   Next relLoop

   dbsNorthwind.Close

End Sub

Public Function RelReport(Optional bSetMarginsAndOrientation As Boolean = True) As Long

    Dim db As DAO.Database      'This database.
    Dim tdf As DAO.TableDef     'Each table referenced in the Relationships window.
    Dim ctl As Control          'Each control on the report.
    Dim lngKt As Long           'Count of tables processed.
    Dim strReportName As String 'Name of the relationships report
    Dim strMsg As String        'MsgBox message.
    
    'Initialize: Open the Relationships report in design view.
    Set db = CurrentDb()
                If TdfSetOk(db, tdf, ctl, strMsg) Then
                    'Change the RowSource to the extended information
                    ctl.RowSource = DescribeFields(tdf)
                    lngKt = lngKt +  1 &  'Count the tables processed successfully.
                End If
Exit_Handler:
    Set db = Nothing
    'Return the number of tables processed.
    RelReport = lngKt
    Exit Function

Err_Handler:
    strMsg = strMsg & "RelReport: Error " & Err.Number & ": " & Err.Description & vbCrLf
    Resume Exit_Handler
End Function

Public Function OpenRelReport(strErrMsg As String) As String
On Error GoTo Err_Handler
    Dim iAccessVersion As Integer     'Access version.
    
    iAccessVersion = Int(Val(SysCmd(acSysCmdAccessVer)))
    Select Case iAccessVersion
    Case Is <  9 
        strErrMsg = strErrMsg & "Requires Access 2000 or later." & vbCrLf
    Case  9 
        RunCommand acCmdRelationships
        SendKeys "%FR", True  'File | Relationships. RunCommand acCmdPrintRelationships is not in A2000.
        RunCommand acCmdDesignView
    Case Is >  9 
        RunCommand acCmdRelationships
        RunCommand  483         ' acCmdPrintRelationships
        RunCommand acCmdDesignView
    End Select
    
    'Return the name of the last report opened
    OpenRelReport = Reports(Reports.Count -  1 &).name

Exit_Handler:
    Exit Function

Err_Handler:
    Select Case Err.Number
        Case  2046 &  'Relationships window is already open.
            'A2000 cannot recover, because SendKeys requires focus on the window.
                If iAccessVersion >  9  Then
                    Resume Next
                Else
                    strErrMsg = strErrMsg & "Close the relationships window, and try again." & vbCrLf
                    Resume Exit_Handler
                End If
        Case  2451 &,  2191 &  'Report not open, or not open in design view.
            strErrMsg = strErrMsg & "The Relationships report must be open in design view." & vbCrLf
            Resume Exit_Handler
        Case Else
            strErrMsg = strErrMsg & "Error " & Err.Number & ": " & Err.Description & vbCrLf
            Resume Exit_Handler
    End Select
End Function

Public Function TdfSetOk(db As DAO.Database, tdf As DAO.TableDef, ctl As Control, strErrMsg As String) As Boolean
On Error GoTo Err_Handler
    Dim strTable As String      'The name of the table.
    
    strTable = ctl.Controls( 0 ).Caption  'Get the name of the table from the attached label's caption.
    Set tdf = db.TableDefs(strTable)    'Fails if the caption is an alias.
    TdfSetOk = True                     'Return true if it all worked.
    
Exit_Handler:
    Exit Function

Err_Handler:
    Select Case Err.Number
    Case  3265 &  'Item not found in collection. (Table name is an alias.)
        strErrMsg = strErrMsg & "Skipped table " & strTable & vbCrLf
    Case Else
        strErrMsg = strErrMsg & "Error " & Err.Number & ": " & Err.Description & vbCrLf
    End Select
    Resume Exit_Handler
End Function

Public Function DescribeFields(tdf As DAO.TableDef) As String
    'Purpose:   Loop through the fields of the table passed in, to create a string _
                    to use as the RowSource of the list box (Value List type).
    Dim fld As DAO.Field        'Each field of the table.
    Dim strReturn As String     'String to build up and return.
    Const strcSep = ";"         'Separator between items in the list box.
    
    For Each fld In tdf.Fields
        'Skip replication info fields.
        If (fld.Attributes And dbSystemField) =  0 & Then
            'strReturn = strReturn & """" & fld.Name & "   "
            strReturn = strReturn & "\le#\FS[8]\FC[0]" & fld.name & " "
            strReturn = strReturn & "\FS[6]\FC[255] - "
            
            'Describe the field type and size.
            Select Case CLng(fld.Type)
                Case dbText
                    strReturn = strReturn & "T" & fld.Size
                    If fld.AllowZeroLength Then
                        strReturn = strReturn & "Z"
                    End If
                Case dbMemo
                    If (fld.Attributes And dbHyperlinkField) <>  0 & Then
                        strReturn = strReturn & "Hyp" 'Hyperlink
                    Else
                        strReturn = strReturn & "M"
                    End If
                    If fld.AllowZeroLength Then
                        strReturn = strReturn & "Z"
                    End If
                Case dbLong
                    If (fld.Attributes And dbAutoIncrField) <>  0 & Then
                        strReturn = strReturn & "A"   'AutoNumber.
                    Else
                        strReturn = strReturn & "L"
                    End If
                Case dbInteger
                    strReturn = strReturn & "Int"
                Case dbCurrency
                    strReturn = strReturn & "C"
                Case dbDate
                    strReturn = strReturn & "Dt"
                Case dbDouble
                    strReturn = strReturn & "Dbl"
                Case dbSingle
                    strReturn = strReturn & "Sng"
                Case dbByte
                    strReturn = strReturn & "B"
                Case dbDecimal
                    strReturn = strReturn & "Dec"
                Case dbBoolean
                    strReturn = strReturn & "Yn"
                Case dbLongBinary
                    strReturn = strReturn & "Ole"
                Case dbGUID
                    strReturn = strReturn & "Guid"
                Case Else
                    strReturn = strReturn & "?"
            End Select
        
            'Assign codes for the field's crucial properties:
            If fld.Required Then            'Required?
                strReturn = strReturn & "R"
            End If                          'Validation Rule?
                If fld.ValidationRule <> vbNullString Then
                    strReturn = strReturn & "V"
                End If                          'Default Value?
                    If fld.DefaultValue <> vbNullString Then
                        strReturn = strReturn & "D"
                    End If
            
            'Indicate if field is indexed.
            strReturn = strReturn & DescribeIndexField(tdf, fld.name) & " " '"""" & strcSep
        End If
    
    strReturn = strReturn & vbCrLf
    Next
    
    DescribeFields = strReturn & "\le#\FS[6]\FC[255]Total Records: " & DCount("*", tdf.name)
    'DescribeFields = strReturn & """     (" & DCount("*", tdf.Name) & ")"""
End Function

Public Function DescribeIndexField(tdf As DAO.TableDef, strField As String) As String

    Dim ind As DAO.Index        'Each index of this table.
    Dim fld As DAO.Field        'Each field of the index
    Dim iCount As Integer
    Dim strReturn As String     'Return string
    
    For Each ind In tdf.Indexes
        iCount =  0 
        For Each fld In ind.Fields
            If fld.name = strField Then
                If ind.Primary Then
                    strReturn = strReturn & IIf(iCount =  0 , "P", "p")
                ElseIf ind.Unique Then
                    strReturn = strReturn & IIf(iCount =  0 , "U", "u")
                Else
                    strReturn = strReturn & IIf(iCount =  0 , "I", "i")
                End If
            End If
            iCount = iCount +  1 
            
        Next
    Next
    
    DescribeIndexField = strReturn
End Function

Public Function SetMarginsAndOrientation(obj As Object) As Boolean

    Const lngcMargin =  720 &     'Margin setting in twips (0.5")
    
    'Access 2000 and earlier do not have the Printer object.
    If Int(Val(SysCmd(acSysCmdAccessVer))) >= 10 Then
        With obj.Printer
            .TopMargin = lngcMargin
            .BottomMargin = lngcMargin
            .LeftMargin = lngcMargin
            .RightMargin = lngcMargin
            .Orientation = 2            'acPRORLandscape not available in A2000.
        End With
        
        'Return True if set.
        SetMarginsAndOrientation = True
    End If
End Function

Public Sub GetBlob(rb As RelBlob, rl() As RelWindow, Optional TheUser As String = "", Optional TheMDB As String = "")

    Dim a() As Byte
    Dim lTemp As Long
    Dim x As Long
    Dim rst As DAO.Recordset
    Dim sSQL As String
    Dim sSel As String
    Dim db As DAO.Database

        If Len(TheUser & vbNullString) > 0 Then
            sSel = TheUser
        Else
            sSel = CurrentUser
        End If
 
            If Len(TheMDB & vbNullString) > 0 Then
                Set db = OpenDatabase(TheMDB, False, True)
            Else
                Set db = CurrentDb()
            End If
 
    sSQL = "SELECT * FROM MSysObjects WHERE NAME = " & """" & sSel & """"
    Set rst = db.OpenRecordset(sSQL, dbOpenDynaset, dbReadOnly)

    lTemp = rst.Fields("LVExtra").FieldSize()

    ReDim a(0 To lTemp)
    a = rst.Fields("LVExtra").GetChunk(0, lTemp)
    
    Set rst = Nothing
    db.Close
    Set db = Nothing

' Fill in our RelBlob header
    CopyMem rb, a(0), Len(rb)

    ReDim rl(0 To rb.NumWindows - 1)
' Fill in our array of structures
        For x = 0 To rb.NumWindows - 1
            CopyMem rl(x), a((x * 284) + 68), 284 '(rb.NumWindows + 1) * 128
        Next x

End Sub

Public Function RelationsToPDF(ctl As Access.Control) As Boolean

    Dim rlBlob() As RelWindow
    ' Copy of RelWindow but with minimal info and no fixed length strings
    Dim rl() As RelWindowMin
    Dim rlTemp() As RelWindowMin
    
    ' The RelationShip window BLOB from the System table
    Dim rb As RelBlob
    
    Dim db As DAO.Database      'This database.
    Dim tdf As DAO.TableDef     'Each table referenced in the Relationships window.
    Dim tdfForeign As DAO.TableDef
     
    Dim SRelTableName As String
    Dim SRelFieldName As String
    Dim sCodes As String
    
    Dim s As String, sTable As String, sForeign As String
    Dim blRet As Boolean
    Dim lRet As Long
    Dim lTemp As Long
    
    ' Current Screen Resolution
    Dim Xdpi As Double
    Dim Ydpi As Double
    Dim lngIC As Long
    Dim ConvX As Double
    Dim ConvY As Double
    
    Dim X1 As Long, X2 As Long, Y1 As Long, Y2 As Long
    Dim X2Max As Long, Y2Max As Long
    Dim X1Prev As Long, Y1Prev As Long
    X2Max = 0
    Y2Max = 0
    Dim ctr As Long
    
    Dim Width As Long
    
    Dim sRect As RECT
 
 ' Reports Device Context
    Dim hdc As Long
    
    Dim newfont As Long
    Dim oldfont As Long
    
     ' Logfont struct
    Dim myfont As LOGFONT
    
    ' TextMetric struct
    Dim tm As TEXTMETRIC
    
    ' LineSpacing Amount
    Dim lngLineSpacing As Long
    
    ' Ttemp var
    Dim numLines As Long
    
    ' Temp string var for current printer name
    Dim strName As String
    
    ' Temp vars
    Dim sngTemp1 As Single
    Dim sngTemp2 As Single
 
    Dim sText As String
    ' RelationShip OrdinalPosition Primary table->Field
    Dim ReOPp As Integer
    ' RelationShip OrdinalPosition Foreign table->Field
    Dim ReOPf As Integer
    Dim fld As DAO.Field
    
    ' inner loop counter
    Dim i As Integer
    
    Dim rel As Relation
    
    ' Let's see if the DynaPDF.DLL is available.
    blRet = LoadLib()

        If blRet = False Then
            ' Cannot find DynaPDF.dll or StrStorage.dll file
            Exit Function
        End If

On Error GoTo ERR_RelationsToPDF

'Initialize: Open the Relationships report in design view.
    Set db = CurrentDb()
    
    sCodes = ""

' Get current Screen DPI
    lngIC = apiCreateIC("DISPLAY", vbNullString, vbNullString, vbNullString)
'If the call to CreateIC didn't fail, then get the Screen X resolution.
        If lngIC <> 0 Then
            Xdpi = apiGetDeviceCaps(lngIC, LOGPIXELSX)
            Ydpi = apiGetDeviceCaps(lngIC, LOGPIXELSY)
            'Release the information context.
            apiDeleteDC (lngIC)
        Else
            ' Something has gone wrong. Assume an average value.
            Xdpi = 120
            Ydpi = 120
        End If

    hdc = apiGetDC(0&)
    
        With ctl
             myfont.lfClipPrecision = CLIP_LH_ANGLES
             myfont.lfOutPrecision = OUT_TT_ONLY_PRECIS
             myfont.lfEscapement = 0
             myfont.lfFaceName = .FontName & Chr$(0)
             myfont.lfWeight = .FontWeight
             myfont.lfItalic = .FontItalic
             myfont.lfUnderline = .FontUnderline
             myfont.lfHeight = (.FontSize / 72) * -Ydpi
             newfont = apiCreateFontIndirect(myfont)
        End With
 
            If newfont = 0 Then
                Err.Raise vbObjectError + 256, "fTextWidthOrHeight", "Cannot Create Font"
            End If

 ' Select the new font into our DC.
    oldfont = apiSelectObject(hdc, newfont)
 
 ' Get TextMetrics. This is required to determine
   ' Text height and the amount of extra spacing between lines.
   lRet = GetTextMetrics(hdc, tm)
    GetBlob rb, rlBlob
' Copy of array of RelWindow structures over to our minimal RelWindow struct
' so we can get rid of unused junk and the fixed length Unicode strings.
ReDim Preserve rl(0 To UBound(rlBlob))

    For ctr = 0 To rb.NumWindows - 1
        With rl(ctr)
            .RelWinX1 = (rlBlob(ctr).RelWinX1) + rb.ScrollBarXoffset
            .RelWinX2 = (rlBlob(ctr).RelWinX2) + rb.ScrollBarXoffset
            .RelWinY1 = (rlBlob(ctr).RelWinY1) + rb.ScrollBarYoffset
            .RelWinY2 = (rlBlob(ctr).RelWinY2) + rb.ScrollBarYoffset
            s = StrConv(rlBlob(ctr).WinName, vbFromUnicode)
            s = Left$(s, InStr(1, s, Chr(0)) - 1)
            .WinName = s
        End With
    Next ctr

' Final Output order of windows
    Dim cOut As New Collection
' Temp working Collection
    Dim cTmp As New Collection

' Current Column Counter
    Dim CurCol As Long
        For ctr = 0 To rb.NumWindows - 1
            With rl(ctr)
                cTmp.Add Item:=ctr, Key:=.WinName
            End With
        Next ctr

' Non existent seed values
    X1Prev = 100000
    Y1Prev = 100000
' Find Top and left most window. Smallet X1 and Y1
    Dim obj As Variant
    Dim sNamePrev As String

' ****************************************************************************************
Dim SpacingInterval As Long

' Add a user defined Left Margin
        Dim LeftMargin As Long
        LeftMargin = 20

SpacingInterval = 200 ' was 200 sat march 11 at 5:57pm200

    For ctr = 0 To rb.NumWindows - 1

        If rl(ctr).RelWinX1 <= SpacingInterval Then
            rl(ctr).RelWinX1 = LeftMargin  '0
        Else
            ' Calculate which column X1 is in.
            lRet = Int(rl(ctr).RelWinX1 / SpacingInterval)
            lTemp = rl(ctr).RelWinX1 - (SpacingInterval * lRet)
            ' Less than half way to next multiple of SpacingInterval
                If lTemp <= SpacingInterval / 2 Then
                    ' Move back
                    lTemp = -lTemp 'SpacingInterval - lTemp
                Else
                    ' More than halfway to next multiple of SpacingInterval
                    ' Move forward
                    lTemp = SpacingInterval - lTemp
                End If
            ' Update coords
            rl(ctr).RelWinX1 = rl(ctr).RelWinX1 + lTemp
            rl(ctr).RelWinX2 = rl(ctr).RelWinX1 + lTemp
            rl(ctr).Column = Int(rl(ctr).RelWinX1 / SpacingInterval)
        End If
    Next ctr
'Next i

' ****************
For ctr = 0 To rb.NumWindows - 1

    For Each obj In cTmp

        
        If rl(obj).RelWinX1 = X1Prev Then
        ' Still in same column
            If rl(obj).RelWinY1 < Y1Prev Then
                Y1Prev = rl(obj).RelWinY1
                X1Prev = rl(obj).RelWinX1
                sNamePrev = rl(obj).WinName
                lRet = obj
            End If
        
        Else
            If rl(obj).RelWinX1 < X1Prev Then
        
            'If rl(obj).RelWinY1 = Y1Prev Then
                Y1Prev = rl(obj).RelWinY1
                X1Prev = rl(obj).RelWinX1
                sNamePrev = rl(obj).WinName
                lRet = obj
            
            'ElseIf rl(obj).RelWinY1 <= Y1Prev Then
            
            End If
        
        
        End If
        
    Next obj

    ' Error checking. Processed all windows
    If Len(sNamePrev & vbNullString) = 0 Then Exit For
    ' Update Column member
    
    
    ' Save off this window in our ordered list
    cOut.Add Item:=lRet, Key:=sNamePrev
    ' Remove this item from the temp work collection
    cTmp.Remove sNamePrev
    ' Reset to non existent seed values
    X1Prev = 100000
    Y1Prev = 100000
    sNamePrev = 0

Next ctr

' Make a working copy
    ReDim rlTemp(0 To UBound(rl))
    rlTemp = rl
    
    ctr = 0
        For Each obj In cOut
            With rl(ctr)
                .RelWinX1 = rlTemp(obj).RelWinX1
                .RelWinY1 = rlTemp(obj).RelWinY1
                .RelWinX2 = rlTemp(obj).RelWinX2
                .RelWinY2 = rlTemp(obj).RelWinY2
                .WinName = rlTemp(obj).WinName
                .Column = rlTemp(obj).Column
                ctr = ctr + 1
            End With
        Next

    Dim MaxDocCharWidth As Long
    Dim MaxDocCharHeight As Long

    sText = "XXXXg"
        With sRect
            .Left = 0
            .Top = 0
            .Bottom = 0
            ' Single line TextWidth
            .Right = 32000
        End With

    lRet = apiDrawText(hdc, sText, -1, sRect, DT_CALCRECT Or DT_TOP Or _
            DT_LEFT Or DT_WORDBREAK Or DT_EXTERNALLEADING Or DT_EDITCONTROL Or DT_NOCLIP)

    MaxDocCharWidth = sRect.Right
    ' Allow for 14 pt header and 10 point leading
    MaxDocCharHeight = sRect.Bottom ' * 2
    
    X2Max = 0
    Y2Max = 0
    Dim bHeader As Boolean

    For ctr = 0 To rb.NumWindows - 1
        With rl(ctr)
            ' Call our function to calc height
            SRelTableName = .WinName '(.WinName) 'StrConv(.WinName, vbFromUnicode)
            s = Right$(SRelTableName, 3)
            lRet = InStr(s, "_")
            If lRet = 1 Or lRet = 2 Then
                SRelTableName = Mid$(SRelTableName, 1, Len(SRelTableName) - (4 - lRet))
            End If
            
                Set tdf = db.TableDefs(SRelTableName) '.WinName)
                    If Not tdf Is Nothing Then
                        'Calc width of Table name and all Field Names
                        ' Set width of Table window to max width
                        sText = tdf.name
                            With sRect
                                .Left = 0
                                .Top = 0
                                .Bottom = 0
                                ' Single line TextWidth
                                .Right = 32000
                            End With
                        
                           lRet = apiDrawText(hdc, sText, -1, sRect, DT_CALCRECT Or DT_TOP Or _
                                    DT_LEFT Or DT_WORDBREAK Or DT_EXTERNALLEADING Or DT_EDITCONTROL Or DT_NOCLIP)
            
                            X2Max = sRect.Right
                            bHeader = True
                            
                        For Each fld In tdf.Fields
                           sText = fld.name
                            With sRect
                                .Left = 0
                                .Top = 0
                                .Bottom = 0
                                ' Single line TextWidth
                                .Right = 32000
                            End With
                        
                           lRet = apiDrawText(hdc, sText, -1, sRect, DT_CALCRECT Or DT_TOP Or _
                                    DT_LEFT Or DT_WORDBREAK Or DT_EXTERNALLEADING Or DT_EDITCONTROL Or DT_NOCLIP)
            
                            If sRect.Right > X2Max Then
                            X2Max = sRect.Right
                            bHeader = False
                            End If
                        Next
                        
                             .RelWinX2 = .RelWinX1 + X2Max + MaxDocCharWidth ' + 16
        
                        Set fld = Nothing
                        X2Max = 0
            
                    End If
            'End If
        
        End With
    Next ctr
Set tdf = Nothing

X2Max = 0
Y2Max = 0
        
        For ctr = 0 To rb.NumWindows - 1
            With rl(ctr)
                ' Call our function to calc height
                SRelTableName = .WinName '(.WinName) 'StrConv(.WinName, vbFromUnicode)
                s = Right$(SRelTableName, 3)
                lRet = InStr(s, "_")
                If lRet = 1 Or lRet = 2 Then
                    SRelTableName = Mid$(SRelTableName, 1, Len(SRelTableName) - (4 - lRet))
                End If
                
                ' Build our string starting with Relationship Table window name
                sText = SRelTableName & vbCrLf
                
                    Set tdf = db.TableDefs(SRelTableName) '.WinName)
                    If Not tdf Is Nothing Then
                        ' Add individual Field names
                                          
                        For Each fld In tdf.Fields
                           sText = sText & fld.name & vbCrLf
                        Next
                            
                          
                            With sRect
                                .Left = 0
                                .Top = 0
                                .Bottom = 0
                                ' Single line TextWidth
                                .Right = 30000 'rl(ctr).RelWinX2 - rl(ctr).RelWinX1
                            End With
                        
                           lRet = apiDrawText(hdc, sText, -1, sRect, DT_CALCRECT Or DT_TOP Or _
                                    DT_LEFT Or DT_WORDBREAK Or DT_EXTERNALLEADING Or DT_EDITCONTROL Or DT_NOCLIP)
                        Y2Max = sRect.Bottom
                                           
                            .RelWinY2 = .RelWinY1 + Y2Max + MaxDocCharHeight
        
                        Set fld = Nothing
            
                    End If
                'End If
            ' ***
            '***********************************************
        
            Dim MinColumnSpacing As Long
            
            MinColumnSpacing = 40
            ' SpacingInterval contains relative offset
            
            End With
        Next ctr

    Set tdf = Nothing
    Set fld = Nothing
    
    
    Dim ctrCol As Long
    'Dim Y1Prev As Long,
    Dim Y2Prev As Long
    Dim Y2PrevOrig As Long, Y1PrevOrig As Long
    Dim VerticalWindowSpacing As Long
    
    VerticalWindowSpacing = 14
    Y1Prev = 0
    Y2Prev = 0
    X2Max = 0
    Y2Max = 0
    ctrCol = 0
    
    Y2PrevOrig = 0
    Y1PrevOrig = 99999999


            For ctr = 0 To rb.NumWindows - 1
                With rl(ctr)
            
                    If .RelWinY1 > Y1PrevOrig Then
                        ' We're still in the same column
                        ' Store Y1
                        Y1PrevOrig = .RelWinY1
                        ' Are we overlapping the previous window in this column.
                            If (.RelWinY1 < Y2Prev + VerticalWindowSpacing) And Y2Prev <> 0 Then
                                ' Reposition to avoid overlap - calc resize first
                                .RelWinY2 = (.RelWinY2 - .RelWinY1) + Y2Prev + VerticalWindowSpacing
                                .RelWinY1 = Y2Prev + VerticalWindowSpacing
                
                '                Y2Prev = .RelWinY2
                '                Y1Prev = .RelWinY1
                                
                            'Else
                            
                            End If
                        Y2Prev = .RelWinY2
                        Y1Prev = .RelWinY1
                        
                    Else
                        ctrCol = ctrCol + 1
                        Y2Prev = .RelWinY2
                            Y1Prev = .RelWinY1
                            Y1PrevOrig = .RelWinY1 '0
                        ' Since we are at top of column no need to reposition
            
                    End If
            
                End With
            Next ctr

    Dim aColWidths() As Long
    
    Dim lNumColumns As Long

' Get Total number of columns
    
    For ctr = 0 To rb.NumWindows - 1
        With rl(ctr)
            If lNumColumns < .Column Then lNumColumns = .Column
        End With
    Next ctr
    

    ReDim aColWidths(0 To lNumColumns)
    Dim Gutter As Long
    Gutter = 20

        For ctr = 0 To rb.NumWindows - 1
            With rl(ctr)
                If (.RelWinX2 - .RelWinX1) > aColWidths(.Column) Then
                    aColWidths(.Column) = (.RelWinX2 - .RelWinX1)
                End If
            End With
        Next ctr


' Set X1 for every table window to the calc start of the column.
' *****************************
' Here we can set the Left Margin
        
        For ctr = 0 To rb.NumWindows - 1
            With rl(ctr)
                ' Column starting position =
                ' column widths for all previous columns plus
                ' column spacing value
                lTemp = 0
                    For i = 0 To .Column - 1
                        lTemp = lTemp + aColWidths(i)
                        lTemp = lTemp + Gutter
                    Next i
                    .RelWinX2 = (.RelWinX2 - .RelWinX1) + lTemp
                    .RelWinX1 = IIf(lTemp = 0, LeftMargin, lTemp)
        
            End With
        Next ctr

    X2Max = 0
    Y2Max = 0
        For ctr = 0 To rb.NumWindows - 1
            With rl(ctr)
                .RelWinX1 = (.RelWinX1 / Xdpi) * 72
                .RelWinX2 = ((.RelWinX2 / Xdpi) * 72) ' + 16
                .RelWinY1 = ((.RelWinY1 / Ydpi) * 72) '+ 16 ' Space for header section
                .RelWinY2 = ((.RelWinY2 / Ydpi) * 72) '+ 6 ' Space for header section
            End With
        
            X2 = rl(ctr).RelWinX2
            Y2 = rl(ctr).RelWinY2
            If X2Max < X2 Then X2Max = X2
            If Y2Max < Y2 Then Y2Max = Y2
        Next ctr

    ctr = 0
    
    Dim sFields As String
    Dim sPDF As String
    
    sPDF = "C:\sourcecode\ReportToPDF\Relations.pdf"
    lRet = BeginPDF(sPDF, X2Max + 32, Y2Max + 32)

            For ctr = 0 To rb.NumWindows - 1
                With rl(ctr)
                    On Error Resume Next
                    SRelTableName = .WinName
                    Set tdf = Nothing
                    
                    Set tdf = db.TableDefs(SRelTableName)
                        If Not tdf Is Nothing Then
                            For Each rel In db.Relations
                                If rel.Table = .WinName Then ' Then
                                    Set fld = rel.Fields(0)
                                    
                                    ReOPp = tdf.Fields(fld.name).OrdinalPosition
                
                                    lRet = 0
                                        If rel.Table = rel.ForeignTable Then
                                            ' Determine which copy(_x) this one is
                                            If Len(rel.Table) * 2 = Len(rel.name) Then
                                                s = rel.ForeignTable & "_" & 1
                                                lRet = 1
                                            Else
                                                s = Right$(rel.name, 1)
                                                s = rel.ForeignTable & "_" & Val(s) + 1
                                                lRet = 1
                                            End If
                                        
                                        End If
                                    
                                    Set tdfForeign = db.TableDefs(rel.ForeignTable)
                                    ReOPf = tdfForeign.Fields(fld.ForeignName).OrdinalPosition + 1
                
                                    X1 = .RelWinX1 '(.RelWinX1 / Xdpi) * 72
                                    Y1 = .RelWinY1 '(.RelWinY1 / Ydpi) * 72
                
                                    Y1 = Y1 + (IIf(ReOPp = 0, 1, ReOPp) * 10)
                
                                        If lRet = 0 Then
                                            s = rel.ForeignTable
                                        End If
                                    
                                            For i = 0 To rb.NumWindows - 1
                                                If rl(i).WinName = s Then 'rel.ForeignTable Then
                                                'If Trim(rl(i).WinName) = rel.ForeignTable Then
                                                    X2 = (rl(i).RelWinX1)
                                                    Y2 = (rl(i).RelWinY1)
                                                    Y2 = Y2 + (IIf(ReOPf = 0, 1, ReOPf) * 10)
                        
                                                    lRet = DrawLine(.RelWinX2 - .RelWinX1, rl(i).RelWinX2 - rl(i).RelWinX1, _
                                                    X1, Y1, X2, Y2, lRet)
                                                End If
                                            Next i
                                    
                                    Set fld = Nothing
                                    Set tdfForeign = Nothing
                                End If
                            Next
                        
                        End If
                    
                End With
                Set tdf = Nothing
            Next ctr


HHH:

        For ctr = 0 To rb.NumWindows - 1
            With rl(ctr)
                On Error Resume Next
                SRelTableName = .WinName '(.WinName) 'StrConv(.WinName, vbFromUnicode)
                s = Right$(SRelTableName, 3)
                lRet = InStr(s, "_")
                    If lRet = 1 Or lRet = 2 Then SRelTableName = Mid$(SRelTableName, 1, Len(SRelTableName) - (4 - lRet))
                        Set tdf = db.TableDefs(SRelTableName)
                            If Not tdf Is Nothing Then
                    
                                sFields = DescribeFields(tdf)
                            End If
                
                lRet = DrawTableWindow(.WinName, sFields, rb.NumWindows, _
                .RelWinX1, .RelWinY1, (.RelWinX2 - .RelWinX1), (.RelWinY2 - .RelWinY1))
            End With
            Set tdf = Nothing
        Next ctr

        ShellExecuteA Application.hWndAccessApp, "open", sPDF, vbNullString, vbNullString, 1

On Error GoTo 0

    lRet = EndPDF
    
    RelationsToPDF = True

EXIT_RelationsToPDF:

    Set db = Nothing
    Set tdf = Nothing
    Set fld = Nothing
    Set rel = Nothing

' If we aready loaded then free the library
    If hLibStrStorage <> 0 Then
        hLibStrStorage = FreeLibrary(hLibStrStorage)
    End If

        If hLibDynaPDF <> 0 Then
            hLibDynaPDF = FreeLibrary(hLibDynaPDF)
        End If


    ' Cleanup
    lRet = apiSelectObject(hdc, oldfont)
    ' Delete the Font we created
    apiDeleteObject (newfont)
   
    ' Release the handle to the Screen's DC
    lRet = apiReleaseDC(0&, hdc)
  
Exit Function

ERR_RelationsToPDF:
MsgBox Err.Description, vbOKOnly, Err.Source & ":" & Err.Number

RelationsToPDF = False
Resume EXIT_RelationsToPDF

End Function

'Вызов
Dim blRet As Boolean

blRet = ConvertReportToPDF(stDocName, vbNullString, _
            stDocName & ".pdf", False, True, 150, "", "", 0, 0, 0)


' Win API "Открытие файла"
' #################################

Private Declare Function apiShellExecute 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
'***App Window Constants***
Public Const WIN_NORMAL = 1 'Open Normal
Public Const WIN_MAX = 2 'Open Maximized
Public Const WIN_MIN = 3 'Open Minimized

'***Error Codes***
Private Const ERROR_SUCCESS = 32&
Private Const ERROR_NO_ASSOC = 31&
Private Const ERROR_OUT_OF_MEM = 0&
Private Const ERROR_FILE_NOT_FOUND = 2&
Private Const ERROR_PATH_NOT_FOUND = 3&
Private Const ERROR_BAD_FORMAT = 11&
Declare Function GetOpenFileName Lib "comdlg32.dll" _
    Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Boolean
Declare Function GetSaveFileName Lib "comdlg32.dll" _
    Alias "GetSaveFileNameA" (pOpenfilename As OPENFILENAME) As Boolean
Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As String
    lpstrCustomFilter As Long
    nMaxCustrFilter As Long
    nFilterIndex As Long
    lpstrFile As String
    nMaxFile As Long
    lpstrFileTitle As String
    nMaxFileTitle As Long
    lpstrInitialDir As String
    lpstrTitle As String
    Flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As String
    lCustrData As Long
    lpfnHook As Long
    lpTemplateName As Long
End Type
Public Const OFN_ALLOWMULTISELECT = &H200
Public Const OFN_CREATEPROMPT = &H2000
Public Const OFN_EXPLORER = &H80000
Public Const OFN_FILEMUSTEXIST = &H1000
Public Const OFN_HIDEREADONLY = &H4
Public Const OFN_NOCHANGEDIR = &H8
Public Const OFN_NODEREFERENCELINKS = &H100000
Public Const OFN_NONETWORKBUTTON = &H20000
Public Const OFN_NOREADONLYRETURN = &H8000
Public Const OFN_NOVALIDATE = &H100
Public Const OFN_OVERWRITEPROMPT = &H2
Public Const OFN_PATHMUSTEXIST = &H800
Public Const OFN_READONLY = &H1
Public Const OFN_SHOWHELP = &H10

Public Function OpenFile(ByVal InitDir As String, ByVal fname As String) As String
    Dim strFile As String * 512
    Dim of As OPENFILENAME
    Dim F As String
    Dim p%
    ' Установка начальных значений структуры
    of.hwndOwner = Application.hWndAccessApp
    of.hInstance = 0
    of.lpstrCustomFilter = 0
    of.nMaxCustrFilter = 0
    of.lpfnHook = 0
    of.lpTemplateName = 0
    of.lCustrData = 0
    'Ниже можно изменить фильтры для поиска файлов
    of.lpstrFilter = "Документы Word (*.doc)" & Chr$(0) & "*.doc" & Chr$(0) & _
    "Книга Microsoft Excel (*.xls)" & Chr$(0) & "*.xls" & Chr$(0) & _
    "Текст в формате RTF (*.rtf)" & Chr$(0) & "*.rtf" & Chr$(0) & _
    "Все файлы (*.*)" & Chr$(0) & "*.*" & Chr$(0) & Chr$(0)
       of.nFilterIndex = 4
    of.lpstrFile = fname & String$(512 - Len(fname), 0)
    of.nMaxFile = 511
    of.lpstrFileTitle = String$(512, 0)
    of.nMaxFileTitle = 511
    ' Ниже можно изменить заголовок окна
    of.lpstrTitle = "Выбор файла"
    of.lpstrInitialDir = InitDir
    ' Можно изменить расширение файла
    of.lpstrDefExt = "*.doc"
    of.Flags = OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST '+ OFN_EXPLORER
    of.lStructSize = Len(of)
    If GetOpenFileName(of) Then
        p% = InStr(1, of.lpstrFile, Chr$(0))
        OpenFile = Left(of.lpstrFile, p% - 1)
    Else
        OpenFile = ""
    End If
End Function

Function fHandleFile(stFile As String, lShowHow As Long)
Dim lRet As Long, varTaskID As Variant
Dim stRet As String
'First try ShellExecute
lRet = apiShellExecute(hWndAccessApp, vbNullString, _
stFile, vbNullString, vbNullString, lShowHow)

    If lRet > ERROR_SUCCESS Then
        stRet = vbNullString
        lRet = -1
    Else
        Select Case lRet
            Case ERROR_NO_ASSOC:
            'Try the OpenWith dialog
                varTaskID = Shell("rundll32.exe shell32.dll,OpenAs_RunDLL " _
                & stFile, WIN_NORMAL)
                lRet = (varTaskID <> 0)
            Case ERROR_OUT_OF_MEM:
                stRet = "Error: Out of Memory/Resources. Couldn't Execute!"
            Case ERROR_FILE_NOT_FOUND:
                stRet = "Error: File not found. Couldn't Execute!"
            Case ERROR_PATH_NOT_FOUND:
                stRet = "Error: Path not found. Couldn't Execute!"
            Case ERROR_BAD_FORMAT:
                stRet = "Error: Bad File Format. Couldn't Execute!"
            Case Else:
                End Select
    End If
        fHandleFile = lRet & _
        IIf(stRet = "", vbNullString, ", " & stRet)
End Function

'Вызов
Private Sub Обзор1_Click()
    If IsNull(Путь1) = True Then
        sSS = OpenFile("c:\", "")
    Else
        sSS = OpenFile(Путь1, "")
    End If
    
        If sSS <> "" Then
            Путь1 = sSS
        End If
End Sub



' Win API "Переход в PDF файле к определенной страницы (указывать нужно полный путь к файлу pdf и номер страницы в pdf)"
' #################################

'Все это вставить в модуль

Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" _
                                                       (ByVal lpFile As String, _
                                                        ByVal lpDirectory As String, _
                                                        ByVal lpResult As String) As Long

Public Sub OpenPDF(FileName As Variant, Optional GoToPage As Long = 1)
' FileName - Полный путь к PDF файлу
' GoToPage - номер страницы на которую надо перейти

On Error GoTo ErrHandler
  
  Dim Error282Count As Integer  ' Количество ошибок "Can't open DDE channel"
  Dim AcroDDEFailed As Boolean  ' Кстанавливается в true если не удалось установить DDE соединение
  Dim strCmd As String          ' DDE команда
  Dim lStatus As Long           ' Ответ команды ShellExecute
  Const Max282Errors = 6        ' Количество попыток установить DDE соединение, перед тем как будет решено
                                ' что Acrobat Reader не удалось запустить.
                                ' Возможно, что число потребуется изменить для конкретного компьютера
  Dim strAcroPath As String     ' Путь к acrobat, определяемый FindExecutable
  Dim lngChanel As Long
  
  Error282Count = Max282Errors '' Количество повторов установить DDE канал
  AcroDDEFailed = False             '' ErrHandler will set to true if Acro is not running
  

'создаем DDE канал
lngChanel = DDEInitiate("acroview", "control")
  ' если возникла ошибка пробуем запустить Acrobat
  If AcroDDEFailed = True Then
   
    ' С помощью FindExecutable пробуем получить путь к программе работы с PDF.
    ' Это может быть Acrobat Reader или Acrobat
    
    strAcroPath = String(128, 32)
    lStatus = FindExecutable(FileName, vbNullString, strAcroPath)
    If lStatus <= 32 Then
      MsgBox "Не найден Acrobat Reader. Открытие файла отменено.", vbCritical, "Ошибка"
      Exit Sub
    End If

    lStatus = Shell(strAcroPath, vbNormalFocus)
    If (lStatus >= 0) And (lStatus <= 32) Then
      MsgBox "Ошибка при запуске Acrobat Reader. Открытие файла отменено", vbCritical, "Ошибка"
      Exit Sub
    End If
   
  End If
  
  PauseFor 2  '' Ждем пока загрузится Acrobat
  Error282Count = 0       'Счетчик ошибок в 0
  AcroDDEFailed = False   '' Acrobat запустился, но может быть еще занят загрузкой файла
 
 'создаем DDE канал
 lngChanel = DDEInitiate("acroview", "control")


  If AcroDDEFailed = True Then
    MsgBox "Ошибка соединения с Acrobat. Открытие файла Отменено", vbCritical, "Ошибка"
    Exit Sub
  End If
 strCmd = "[DocOpen(" & Chr(34) & FileName & Chr(34) & ")]"
 strCmd = strCmd & "[FileOpen(" & Chr(34) & FileName & Chr(34) & ")]"
 strCmd = strCmd & "[DocGoTo(" & Chr(34) & FileName & Chr(34) & "," & GoToPage - 1 & ")]"
' теоретически здесь вместо DocGoTo можно использовать DocGoToNameDest с указанием
' имени закладки, но практически не пробовал
 
DDEExecute lngChanel, strCmd
   
  'Закрываем все DDE
 DDETerminateAll
Exit Sub

ErrHandler:
  If Err.Number = 282 Then 'Невозможно открыть DDE канал
    ' Эта ошибка может возникать когда Acrobat загрузился не польностью
    ' делаем Max282Errors попыток перед тем как вернуть AcroDDEFailed = True
    Error282Count = Error282Count + 1
    If Error282Count <= Max282Errors Then
      PauseFor 3
      Resume
    Else
      AcroDDEFailed = True
      Resume Next
    End If
  End If
  
  MsgBox "Error in OpenPDF sub Error# " & Err.Number & " " & Err.Description & "."
End Sub

' вспомогательная функция
Private Sub PauseFor(iSeconds As Integer)
'Пауза iSecond секунд
  Dim sngTimer As Single
  
  sngTimer = Timer
  While Timer - sngTimer < iSeconds
    DoEvents
  Wend

End Sub

'Указывать полный путь к файлу PDF, поиск осуществляется по необходимому слову

Sub AcrobatFindText()
'IAC objects
Dim gApp As CAcroApp
Dim gAvDoc As CAcroAVDoc
'variables
Dim Resp 'For message box responses
Dim gPDFPath As String
Dim sText As String
'String to search for
Dim sStr As String
'Message string
Dim foundText As Integer
'Holds return value from "FindText" method
'hard coding for a PDF to open, it can be changed when needed.
gPDFPath = "C:\PreviewWork\2003.pdf"
'Initialize Acrobat by creating App objectSet
Set gApp = CreateObject("AcroExch.App")
gApp.Hide
'Set AVDoc objectSet
Set gAvDoc = CreateObject("AcroExch.AVDoc")
' open the PDF
If gAvDoc.Open(gPDFPath, "") Then
sText = "дела"
'FindText params: StringToSearchFor, caseSensitive (1 or 0), WholeWords (1 or 0), ResetSearchToBeginOfDocument (1 or 0)
foundText = gAvDoc.FindText(sText, 1, 0, 1)
'Returns -1 if found, 0 otherwise
Else ' if failed, show errormessage
Resp = MsgBox("Cannot open" & gPDFPath, vbOKOnly)
End If
If foundText = -1 Then
'compose amessage
sStr = "Found " & sText
Resp = MsgBox(sStr, vbOKOnly)
Else
' if failed, show errormessage
Resp = MsgBox("Cannot find" & sText, vbOKOnly)
End If
gApp.Show
gAvDoc.BringToFront
 End Sub
  
 
' WinAPI Если нужно при свернутом или неактивном окне MS ACCESS, вывести какое-либо сообщение пользователю, это можно сделать с помощью приведенного кода.
 '############################
 
Option Compare Database

Option Explicit
Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" _
                                (ByVal dwExStyle As Long, _
                                 ByVal lpClassName As String, _
                                 ByVal lpWindowName As String, _
                                 ByVal dwStyle As Long, _
                                 ByVal x As Long, _
                                 ByVal y As Long, _
                                 ByVal nWidth As Long, _
                                 ByVal nHeight As Long, _
                                 ByVal hWndParent As Long, _
                                 ByVal hMenu As Long, _
                                 ByVal hInstance As Long, _
                                 lpParam As Any) As Long

Declare Function LoadIcon Lib "user32" Alias "LoadIconA" _
                                (ByVal hInstance As Long, _
                                 ByVal lpIconName As String) As Long
Declare Function LoadCursor Lib "user32" Alias "LoadCursorA" _
                                (ByVal hInstance As Long, _
                                ByVal lpCursorName As String) As Long
Declare Function GetStockObject Lib "gdi32" (ByVal nIndex As Long) As Long
Declare Function RegisterClassEx Lib "user32" Alias "RegisterClassExA" _
                                (pcWndClassEx As WNDCLASSEX) As Integer
Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, _
                                          ByVal nCmdShow As Long) As Long
Declare Function UpdateWindow Lib "user32" (ByVal hwnd As Long) As Long
Declare Function SetFocus Lib "user32" (ByVal hwnd As Long) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
                                        (ByVal hwnd As Long, _
                                        ByVal wMsg As Long, _
                                        ByVal wParam As Long, _
                                        ByVal lParam As Long) As Long
Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" _
                                        (ByVal hwnd As Long, _
                                        ByVal wMsg As Long, _
                                        ByVal wParam As Long, _
                                        ByVal lParam As Long) As Long
Declare Function GetMessage Lib "user32" Alias "GetMessageA" _
                                        (lpMsg As MSG, _
                                        ByVal hwnd As Long, _
                                        ByVal wMsgFilterMin As Long, _
                                        ByVal wMsgFilterMax As Long) As Long
Declare Function TranslateMessage Lib "user32" (lpMsg As MSG) As Long
Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (lpMsg As MSG) As Long
Declare Sub PostQuitMessage Lib "user32" (ByVal nExitCode As Long)
Declare Function BeginPaint Lib "user32" (ByVal hwnd As Long, lpPaint As PAINTSTRUCT) As Long
Declare Function EndPaint Lib "user32" (ByVal hwnd As Long, lpPaint As PAINTSTRUCT) As Long
Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hdc As Long, _
                                                          ByVal lpStr As String, _
                                                          ByVal nCount As Long, _
                                                          lpRect As RECT, _
                                                          ByVal wFormat As Long) As Long
Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hwnd As Long, _
                                                          ByVal crKey As Long, _
                                                          ByVal bAlpha As Byte, _
                                                          ByVal dwFlags As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
                                                (ByVal hwnd As Long, _
                                                ByVal nIndex As Long) As Long

Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
                                                (ByVal hwnd As Long, _
                                                ByVal nIndex As Long, _
                                                ByVal dwNewLong As Long) As Long

Type WNDCLASSEX
cbSize As Long
style As Long
lpfnWndProc As Long
cbClsExtra As Long
cbWndExtra As Long
hInstance As Long
hIcon As Long
hCursor As Long
hbrBackground As Long
lpszMenuName As String
lpszClassName As String
hIconSm As Long
End Type


Type POINTAPI
x As Long
y As Long
End Type

Type MSG
hwnd As Long
message As Long
wParam As Long
lParam As Long
time As Long
pt As POINTAPI
End Type

Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type

Type PAINTSTRUCT
hdc As Long
fErase As Long
rcPaint As RECT
fRestore As Long
fIncUpdate As Long
rgbReserved(32) As Byte
End Type

Public Const WS_VISIBLE As Long = &H10000000
Public Const WS_VSCROLL As Long = &H200000
Public Const WS_TABSTOP As Long = &H10000
Public Const WS_THICKFRAME As Long = &H40000
Public Const WS_MAXIMIZE As Long = &H1000000
Public Const WS_MAXIMIZEBOX As Long = &H10000
Public Const WS_MINIMIZE As Long = &H20000000
Public Const WS_MINIMIZEBOX As Long = &H20000
Public Const WS_SYSMENU As Long = &H80000
Public Const WS_BORDER As Long = &H800000
Public Const WS_CAPTION As Long = &HC00000
Public Const WS_CHILD As Long = &H40000000
Public Const WS_CHILDWINDOW As Long = (WS_CHILD)
Public Const WS_CLIPCHILDREN As Long = &H2000000
Public Const WS_CLIPSIBLINGS As Long = &H4000000
Public Const WS_DISABLED As Long = &H8000000
Public Const WS_DLGFRAME As Long = &H400000
Public Const WS_EX_ACCEPTFILES As Long = &H10&
Public Const WS_EX_DLGMODALFRAME As Long = &H1&
Public Const WS_EX_NOPARENTNOTIFY As Long = &H4&
Public Const WS_EX_TOPMOST As Long = &H8&
Public Const WS_EX_TRANSPARENT As Long = &H20&
Public Const WS_GROUP As Long = &H20000
Public Const WS_HSCROLL As Long = &H100000
Public Const WS_ICONIC As Long = WS_MINIMIZE
Public Const WS_OVERLAPPED As Long = &H0&
Public Const WS_OVERLAPPEDWINDOW As Long = (WS_OVERLAPPED Or _
                                            WS_CAPTION Or _
                                            WS_SYSMENU Or _
                                            WS_THICKFRAME Or _
                                            WS_MINIMIZEBOX Or _
                                            WS_MAXIMIZEBOX)
Public Const WS_POPUP As Long = &H80000000
Public Const WS_POPUPWINDOW As Long = (WS_POPUP Or WS_BORDER Or WS_SYSMENU)
Public Const WS_SIZEBOX As Long = WS_THICKFRAME
Public Const WS_TILED As Long = WS_OVERLAPPED
Public Const WS_TILEDWINDOW As Long = WS_OVERLAPPEDWINDOW
Public Const CW_USEDEFAULT As Long = &H80000000
Public Const CS_HREDRAW As Long = &H2
Public Const CS_VREDRAW As Long = &H1
Public Const IDI_APPLICATION As Long = 32512&
Public Const IDC_ARROW As Long = 32512&
Public Const WHITE_BRUSH As Integer = 0
Public Const BLACK_BRUSH As Integer = 4
Public Const WM_KEYDOWN As Long = &H100
Public Const WM_CLOSE As Long = &H10
Public Const WM_DESTROY As Long = &H2
Public Const WM_PAINT As Long = &HF
Public Const SW_SHOWNORMAL As Long = 1
Public Const DT_CENTER As Long = &H1
Public Const DT_SINGLELINE As Long = &H20
Public Const DT_VCENTER As Long = &H4
Public Const WS_EX_PALETTEWINDOW As Long = &H188
Public Const LWA_ALPHA = &H2
Public Const GWL_EXSTYLE = (-20)
Public Const WS_EX_LAYERED = &H80000
Dim strMessage As String
________________________________________


Public Function displayMessage(mess As String) As Long
strMessage = mess
Const CLASSNAME = "mymsg"
Const Title = " Пришло сообщение"
Dim hwnd As Long
Dim wc As WNDCLASSEX
Dim message As MSG

wc.cbSize = Len(wc)
wc.style = CS_HREDRAW Or CS_VREDRAW
wc.lpfnWndProc = GetFuncPtr(AddressOf WindowProc)
wc.cbClsExtra = 0&
wc.cbWndExtra = 0&
wc.hInstance = Application.hWndAccessApp
wc.hIcon = LoadIcon(Application.hWndAccessApp, IDI_APPLICATION)
wc.hCursor = LoadCursor(Application.hWndAccessApp, IDC_ARROW)
wc.hbrBackground = GetStockObject(WHITE_BRUSH)
wc.lpszMenuName = 0&
wc.lpszClassName = CLASSNAME
wc.hIconSm = LoadIcon(Application.hWndAccessApp, IDI_APPLICATION)

RegisterClassEx wc

hwnd = CreateWindowEx(WS_EX_PALETTEWINDOW, _
CLASSNAME, _
Title, _
WS_OVERLAPPEDWINDOW, _
800, _
500, _
200, _
300, _
0&, _
0&, _
Application.hWndAccessApp, _
0&)


ShowWindow hwnd, SW_SHOWNORMAL
UpdateWindow hwnd
SetFocus hwnd


Do While 0 <> GetMessage(message, 0&, 0&, 0&)
TranslateMessage message
DispatchMessage message
Loop

displayMessage = message.wParam
End Function
________________________________________
Public Function WindowProc(ByVal hwnd As Long, _
                           ByVal message As Long, _
                           ByVal wParam As Long, _
                           ByVal lParam As Long) As Long

Dim ps As PAINTSTRUCT
Dim rc As RECT
Dim hdc As Long

Select Case message

Case WM_PAINT
hdc = BeginPaint(hwnd, ps)
Call GetClientRect(hwnd, rc)

Call DrawText(hdc, strMessage, Len(strMessage), rc, DT_SINGLELINE Or _
               DT_CENTER Or DT_VCENTER)
Call EndPaint(hwnd, ps)

Dim Ret As Long
Ret = GetWindowLong(hwnd, GWL_EXSTYLE)
Ret = Ret Or WS_EX_LAYERED
SetWindowLong hwnd, GWL_EXSTYLE, Ret

SetLayeredWindowAttributes hwnd, 0, 200, LWA_ALPHA

Exit Function

Case WM_KEYDOWN
Call PostMessage(hwnd, WM_CLOSE, 0, 0)
Exit Function

Case WM_DESTROY
PostQuitMessage 0&
Exit Function

Case Else

WindowProc = DefWindowProc(hwnd, message, wParam, lParam)

End Select


End Function
________________________________________
Function GetFuncPtr(ByVal lngFnPtr As Long) As Long
GetFuncPtr = lngFnPtr
End Function

'Пример вызова
Call displayMessage("обработка завершена")


'Экспорт в PDF с помощью PDFCreator (вдруг пригодится)
'###############################

Sub PrintAccessReportToPDF_Early()
'Author       : Ken Puls ( www.excelguru.ca)
'Macro Purpose: Print to PDF file using PDFCreator
'   (Download from http://sourceforge.net/projects/pdfcreator/ )
'   Designed for early bind, set reference to PDFCreator

    Dim pdfjob As PDFCreator.clsPDFCreator
    Dim sPDFName As String
    Dim sPDFPath As String
    Dim sPrinterName As String
    Dim sReportName As String
    Dim lPrinters As Long
    Dim lPrinterCurrent As Long
    Dim lPrinterPDF As Long
    Dim prtDefault As Printer

    '/// Change the report and output file name here! ///
    sReportName = "Chart of Accounts"
    sPDFName = sReportName & ".pdf"
    sPDFPath = Application.CurrentProject.path & "\"

    'Resolve index number of printers to allow changing and preserving
    sPrinterName = Application.Printer.DeviceName
    On Error Resume Next
    For lPrinters = 0 To Application.Printers.Count
        Set Application.Printer = Application.Printers(lPrinters)

        Set prtDefault = Application.Printer
        Select Case prtDefault.DeviceName
            Case Is = sPrinterName
                lPrinterCurrent = lPrinters
            Case Is = "PDFCreator"
                lPrinterPDF = lPrinters
            Case Else
                'do nothing
        End Select
    Next lPrinters
    On Error GoTo 0
   
    'Change the default printer
    Set Application.Printer = Application.Printers(lPrinterPDF)
    Set prtDefault = Application.Printer

    'Start PFF Creator
    Set pdfjob = New PDFCreator.clsPDFCreator
    With pdfjob
        If .cStart("/NoProcessingAtStartup") = False Then
            MsgBox "Can't initialize PDFCreator.", vbCritical + _
                    vbOKOnly, "PrtPDFCreator"
            Exit Sub
        End If
        .cOption("UseAutosave") = 1
        .cOption("UseAutosaveDirectory") = 1
        .cOption("AutosaveDirectory") = sPDFPath
        .cOption("AutosaveFilename") = sPDFName
        .cOption("AutosaveFormat") = 0    ' 0 = PDF
        .cClearCache
    End With

    'Print the document to PDF
    DoCmd.OpenReport (sReportName)
   
    'Wait until the print job has entered the print queue
    Do Until pdfjob.cCountOfPrintjobs = 1
        DoEvents
    Loop
    pdfjob.cPrinterStop = False

    'Wait until PDF creator is finished then release the objects
    Do Until pdfjob.cCountOfPrintjobs = 0
        DoEvents
    Loop
    pdfjob.cClose

    'Reset the (original) default printer and release PDF Creator
    Set Application.Printer = Application.Printers(lPrinterCurrent)
    Set pdfjob = Nothing
End Sub


'Вывод сообщения в разных местах монитора
'###############################

'**********************************************************************
' * Comments         : Controlling the position of a MsgBox
' *
' * You can create a CBT hook for your application so that it receives
' * notifications when windows are created and destroyed. If you
' * display a message box with this CBT hook in place, your application
' * will receive a HCBT_ACTIVATE message when the message box is
' * activated. Once you receive this HCBT_ACTIVATE message, you can
' * position the window with the SetWindowPos API function and then
' * release the CBT hook if it is no longer needed. See the "Test"
' * routine for a demonstration.
' *
' **********************************************************************

'PLACE CODE IN A STANDARD MODULE

Public Enum ePosMsgBox
   eTopLeft
   eTopRight
   eTopCentre
   eBottomLeft
   eBottomRight
   eBottomCentre
   eCentreScreen
   eCentreDialog
End Enum

Private Type RECT
   Left                 As Long
   Top                  As Long
   Right                As Long
   Bottom               As Long
End Type

'Message API and constants
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal zlhHook As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) 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 GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Const GWL_HINSTANCE = (-6)
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOZORDER = &H4
Private Const SWP_NOACTIVATE = &H10
Private Const HCBT_ACTIVATE = 5
Private Const WH_CBT = 5

'Other APIs
Private Declare Function GetForegroundWindow Lib "user32" () As Long
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 zlhHook         As Long
Private zePosition      As ePosMsgBox

'Purpose : Displays a msgbox at a specified location on the screen
'Inputs : As per a standard MsgBox +
' Position An enumerated type which controls the screen position of the MsgBox
'Outputs : As per a standard Msgbox
'Author : Andrew Baker
'Date : 25/05/2001
'Notes :

Function MsgboxEx(Prompt As String, Optional Buttons As VbMsgBoxStyle, Optional Title As String, Optional HelpFile As String, Optional Context As Long, Optional Position As ePosMsgBox = eCentreScreen) As VbMsgBoxResult
   Dim lhInst           As Long
   Dim lThread          As Long

   'Set up the CBT hook
   lhInst = GetWindowLong(GetForegroundWindow, GWL_HINSTANCE)
   lThread = GetCurrentThreadId()
   zlhHook = SetWindowsHookEx(WH_CBT, AddressOf zWindowProc, lhInst, lThread)

   zePosition = Position

   'Display the message box
   MsgboxEx = MsgBox(Prompt, Buttons, Title, HelpFile, Context)
End Function

'Call back used by MsgboxEx
Function zWindowProc(ByVal lMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
   Dim tFormPos         As RECT, tMsgBoxPos As RECT, tScreenWorkArea As RECT
   Dim lLeft            As Long, lTop As Long

   If lMsg = HCBT_ACTIVATE Then
      On Error Resume Next
      'A new dialog has been displayed
      tScreenWorkArea = ScreenWorkArea
      'Get the coordinates of the form and the message box so that
      'you can determine where the center of the form is located
      GetWindowRect GetForegroundWindow, tFormPos
      GetWindowRect wParam, tMsgBoxPos

      Select Case zePosition
         Case eCentreDialog
            lLeft = (tFormPos.Left + (tFormPos.Right - tFormPos.Left) / 2) - ((tMsgBoxPos.Right - tMsgBoxPos.Left) / 2)
            lTop = (tFormPos.Top + (tFormPos.Bottom - tFormPos.Top) / 2) - ((tMsgBoxPos.Bottom - tMsgBoxPos.Top) / 2)

         Case eCentreScreen
            lLeft = ((tScreenWorkArea.Right - tScreenWorkArea.Left) - (tMsgBoxPos.Right - tMsgBoxPos.Left)) / 2
            lTop = ((tScreenWorkArea.Bottom - tScreenWorkArea.Top) - (tMsgBoxPos.Bottom - tMsgBoxPos.Top)) / 2

         Case eTopLeft
            lLeft = tScreenWorkArea.Left
            lTop = tScreenWorkArea.Top

         Case eTopRight
            lLeft = tScreenWorkArea.Right - (tMsgBoxPos.Right - tMsgBoxPos.Left)
            lTop = tScreenWorkArea.Top

         Case eTopCentre
            lLeft = ((tScreenWorkArea.Right - tScreenWorkArea.Left) - (tMsgBoxPos.Right - tMsgBoxPos.Left)) / 2
            lTop = tScreenWorkArea.Top

         Case eBottomLeft
            lLeft = tScreenWorkArea.Left
            lTop = tScreenWorkArea.Bottom - (tMsgBoxPos.Bottom - tMsgBoxPos.Top)

         Case eBottomRight
            lLeft = tScreenWorkArea.Right - (tMsgBoxPos.Right - tMsgBoxPos.Left)
            lTop = tScreenWorkArea.Bottom - (tMsgBoxPos.Bottom - tMsgBoxPos.Top)

         Case eBottomCentre
            lLeft = ((tScreenWorkArea.Right - tScreenWorkArea.Left) - (tMsgBoxPos.Right - tMsgBoxPos.Left)) / 2
            lTop = tScreenWorkArea.Bottom - (tMsgBoxPos.Bottom - tMsgBoxPos.Top)

      End Select

      'Position the msgbox
      SetWindowPos wParam, 0, lLeft, lTop, 10, 10, SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOACTIVATE

      'Release the CBT hook
      UnhookWindowsHookEx zlhHook
   End If
   zWindowProc = False

End Function

'Purpose : Returns the screen dimensions, not including the tastbar
'Inputs : N/A
'Outputs : A type which defines the extent of the screen work area.
'Author : Andrew Baker
'Date : 25/05/2001
'Notes :

Function ScreenWorkArea() As RECT
   Dim tScreen          As RECT
   Dim lRet             As Long
   Const SPI_GETWORKAREA = 48

   lRet = SystemParametersInfo(SPI_GETWORKAREA, vbNull, tScreen, 0)
   ScreenWorkArea = tScreen
End Function

'Demonstration routine
Sub Test()
   MsgboxEx "Hello BottomCentre", , , , , eBottomCentre
   MsgboxEx "Hello BottomLeft", , , , , eBottomLeft
   MsgboxEx "Hello BottomRight", , , , , eBottomRight
   MsgboxEx "Hello CentreDialog", , , , , eCentreDialog
   MsgboxEx "Hello CentreScreen", , , , , eCentreScreen
   MsgboxEx "Hello TopCentre", , , , , eTopCentre
   MsgboxEx "Hello TopLeft", , , , , eTopLeft
   MsgboxEx "Hello TopRight", , , , , eTopRight
End Sub

'Вызов

Private Sub TestMsgBox_Click()

' просмотр возможных вариантов вывода (процедура "Test" в модуле):
Test

' или одна из позиций на выбор:
   '  MsgboxEx "Hello BottomCentre", , , , , eBottomCentre
   '  MsgboxEx "Hello BottomLeft", , , , , eBottomLeft
   '  MsgboxEx "Hello BottomRight", , , , , eBottomRight
   '  MsgboxEx "Hello CentreDialog", , , , , eCentreDialog
   '  MsgboxEx "Hello CentreScreen", , , , , eCentreScreen
   '  MsgboxEx "Hello TopCentre", , , , , eTopCentre
   '  MsgboxEx "Hello TopLeft", , , , , eTopLeft
   '  MsgboxEx "Hello TopRight", , , , , eTopRight
End Sub
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37319807
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
похоже слова сбываются

0524WRXХочу создать тему - Функции WinApi и Access - и выложить туда коды - поддержит меня аудитория?
если не поддержит так тема сама "утонет"
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37319822
П-Л
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дык, хорошо бы было модератором эту тему наверху прибить а еще лучше в ФАКЕ такой раздел организовать, а там хорошо было бы общий спойлер на отдельный разбить, по каждому разделу. Вещь крайне полезная.
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37319867
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
П-ЛДык, хорошо бы было модератором эту тему наверху прибить а еще лучше в ФАКЕ такой раздел организовать, а там хорошо было бы общий спойлер на отдельный разбить, по каждому разделу. Вещь крайне полезная.
Это обязательно будет сделано, как только станет известно, что список готов.
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37319888
ё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ё
Гость
П-ЛДык, хорошо бы было модератором эту тему наверху прибить а еще лучше в ФАКЕ такой раздел организовать, а там хорошо было бы общий спойлер на отдельный разбить, по каждому разделу. Вещь крайне полезная.
+1
сюда, хотя бы для начала
Ссылки на недоделанные FAQ
может ещё что-то добавят...
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37319916
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
Владимир СанычП-ЛДык, хорошо бы было модератором эту тему наверху прибить а еще лучше в ФАКЕ такой раздел организовать, а там хорошо было бы общий спойлер на отдельный разбить, по каждому разделу. Вещь крайне полезная.
Это обязательно будет сделано, как только станет известно, что список готов.

Владимир Саныч: список полным никогда не будет...
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37320265
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
Функции WinAPI

Как заблокировать закрытие окна Access по Alt+F4 (привет от Бенедикта)
Код: plaintext
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.
'Иногда (а у меня довольно часто) бывает необходимо заставить пользователя правильно закрыть приложение: т.е. последовательно закрыть все открытые формы, а потом и само приложение специальной кнопкой (или пунктом меню) на которой весит команда DoCmd.Quit. Но некоторые пользователи имеют дурную привычку закрывать приложение при помощи крестика оконного меню (справа вверху). Или при помощи комбинации клавиш Alt+F4.
'Как заблокировать кнопку закрытия окна Access можно прочитать в статье Disable кнопку закрытия окна MsAccess . А вот с блокировкой закрытия Access через Alt+F4 пришлось немного повозиться. Поиск в Интернете привел меня на сайт VB Forums . Здесь в топике Disable ALT-F4  пользователь под ником Lord Orvell предложил код для блокировки сочетаний клавиш Ctrl+Esc, Alt+Tab, Alt+Esc для программ на VB. Дмитрий Милосердов (aka Бенедикт) с сайта SQL.RU доработал предложенный код для использования его в программах Access VBA. Для работы требуется ОС Windows NT4 с SP 3 и выше.

Option Compare Database
 Option Explicit

Private Declare Function GetForegroundWindow Lib "user32" () As Long
 Private Declare Function GetWindowThreadProcessId Lib "user32" ( _
 ByVal hWnd As Long, lpdwProcessId As Any) As Long

Private Declare Function GetModuleHandle Lib "kernel32" _
 Alias "GetModuleHandleA" ( _
 ByVal lpModuleName As String) As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
 pDest As Any, pSource As Any, ByVal cb As Long)

Private Const WH_KEYBOARD_LL =  13 &

Private Const HC_ACTION =  0 &

Private Type KBDLLHOOKSTRUCT
 vkCode As Long
 scanCode As Long
 flags As Long
 time As Long
 dwExtraInfo As Long
 End Type

Private Const LLKHF_ALTDOWN = &H20&

Private Declare Function SetWindowsHookEx Lib "user32" _
 Alias "SetWindowsHookExA" ( _
 ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, _
 ByVal dwThreadId As Long) As Long
 Private Declare Function UnhookWindowsHookEx Lib "user32" ( _
 ByVal hHook As Long) As Long
 Private Declare Function CallNextHookEx Lib "user32" ( _
 ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, _
 ByVal lParam As Long) As Long

Private m_hLLKbdHook As Long
 Private m_AccAppProcessId As Long

'----------------------------------------------------------------------------
 ' Purpose : Блокировка сочетания клавишь Alt+F4
 '----------------------------------------------------------------------------
 '
 Public Sub BlockAltF4()
      If m_hLLKbdHook Then
           Debug.Print "Low level keyboard hook already installed!"
           Exit Sub
      End If
      GetWindowThreadProcessId Application.hWndAccessApp, m_AccAppProcessId
      m_hLLKbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, _
      AddressOf LowLevelKeyboardProc, GetModuleHandle(vbNullString),  0 &)
      If m_hLLKbdHook Then
           Debug.Print "Alt+F4 blocked."
      Else
           MsgBox "Failed to install low-level keyboard hook - " & Err.LastDllError
      End If
 End Sub

'----------------------------------------------------------------------------
 ' Purpose : Разблокировка сочетания клавишь Alt+F4
 '----------------------------------------------------------------------------
 '
 Public Sub UnblockAltF4()
      If m_hLLKbdHook Then
           UnhookWindowsHookEx m_hLLKbdHook
           m_hLLKbdHook =  0 
           Debug.Print "Alt+F4 unblocked."
      End If
 End Sub

 Public Function LowLevelKeyboardProc(ByVal nCode As Long, _
      ByVal wParam As Long, _
      ByVal lParam As Long) As Long
      Debug.Print "LowLevelKeyboardProc", nCode, wParam, Hex$(lParam)
      Dim kbdllhs As KBDLLHOOKSTRUCT
      If nCode = HC_ACTION Then
           CopyMemory kbdllhs, ByVal lParam, Len(kbdllhs)
           If (kbdllhs.vkCode = vbKeyF4) And (kbdllhs.flags And LLKHF_ALTDOWN) Then
                Dim ForeProcessId As Long
                GetWindowThreadProcessId GetForegroundWindow, ForeProcessId
                If m_AccAppProcessId = ForeProcessId Then
                     Debug.Print "Alt+F4 blocked."
                     LowLevelKeyboardProc =  1 
                     Exit Function
                End If
           End If
      End If
      LowLevelKeyboardProc = CallNextHookEx(m_hLLKbdHook, nCode, wParam, lParam)
 End Function
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37322955
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
http://www.interface.ru/home.asp?artId=8171

Тут более красиво про выключение компьютера и разлогинивание (в терминале удобно).
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37348282
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
изменение приорите программы

Код: plaintext
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.
'в модуль:
Option Explicit
Public Const TH32CS_SNAPPROCESS As Long =  2 &
Public Const MAX_PATH As Integer =  260 
Public 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
Public Declare Function CreateToolhelpSnapshot Lib "kernel32" Alias "CreateToolhelp32Snapshot" (ByVal lFlags As Long, ByVal lProcessID As Long) As Long
Public Declare Function SetPriorityClass Lib "kernel32" (ByVal hProcess As Long, ByVal dwPriorityClass As Long) As Long
Public Const IDLE_PRIORITY_CLASS = &H40
Public Const NORMAL_PRIORITY_CLASS = &H20
Public Const HIGH_PRIORITY_CLASS = &H80
Public Const REALTIME_PRIORITY_CLASS = &H100
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Declare Function ProcessFirst Lib "kernel32" Alias "Process32First" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
Public Declare Function ProcessNext Lib "kernel32" Alias "Process32Next" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long

Public Function PriorityApp(myName As String, mySPrior As Long) As Boolean
    Const PROCESS_ALL_ACCESS =  0 
    Dim uProcess As PROCESSENTRY32
    Dim rProcessFound As Long
    Dim hSnapshot As Long
    Dim szExename As String
    Dim exitCode As Long
    Dim myProcess As Long
    Dim AppSet As Boolean
    Dim appCount As Integer
    Dim i As Integer
    appCount =  0 
    uProcess.dwSize = Len(uProcess)
    hSnapshot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS,  0 & 
    rProcessFound = ProcessFirst(hSnapshot, uProcess)
    Do While rProcessFound
        i = InStr( 1 , uProcess.szExeFile, Chr( 0 ))
        szExename = LCase$(Left$(uProcess.szExeFile, i -  1 ))
        If Right$(szExename, Len(myName)) = LCase$(myName) Then
            AppSet = True
            appCount = appCount +  1 
            myProcess = OpenProcess(PROCESS_ALL_ACCESS, False, uProcess.th32ProcessID)
            AppSet = SetPriorityClass(myProcess, mySPrior)
            Exit Function
        End If
        rProcessFound = ProcessNext(hSnapshot, uProcess)
    Loop
    Call CloseHandle(hSnapshot)
End Function

'в форму или куда хошь...
'ставит калькулятору реал-тайм (самый высокий) приоритет.
Private Sub Command1_Click()
Call PriorityApp("C:\Windows\calc.exe", REALTIME_PRIORITY_CLASS)
End Sub
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37352856
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37353031
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
прокрутка формы
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37353094
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WRX,

весьма полезно, попробую переделать под горизонтальную полосу.
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37353367
WRX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WRX
Гость
alvkWRX,

весьма полезно, попробую переделать под горизонтальную полосу.

будет великолепно
...
Рейтинг: 0 / 0
Использование функций WinAPI в Access
    #37353432
Фотография Бенедикт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WRX,

для горизонтальной прокрутки внести следующие изменения в класс CCustomScrollForm:
Код: plaintext
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.
'Класс, прокручивающий форму и блокирующий прокрутку записей.

Option Compare Database
Option Explicit


Private Const WM_HSCROLL = &H114
Private Const SB_LINELEFT =  0 
Private Const SB_LINERIGHT =  1 
'Private Const WM_VSCROLL = &H115
'Private Const SB_LINEUP = 0
'Private Const SB_LINEDOWN = 1
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" ( _
   ByVal hWnd As Long, ByVal wMsg As Long, _
   ByVal wParam As Long, lParam As Any) As Long


Private m_Form As Access.Form
Private WithEvents m_mwet As CMouseWheelEventTracker


Public Property Get Form() As Access.Form
 Set Form = m_Form
End Property

Public Property Set Form(ByVal NewForm As Access.Form)
 Set m_mwet = Nothing
 Set m_Form = NewForm
 If Not NewForm Is Nothing Then
    Set m_mwet = New CMouseWheelEventTracker
    m_mwet.hWnd = NewForm.hWnd
 End If
End Property


Private Sub m_mwet_MouseWheel(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single, ByVal Delta As Integer, Cancel As Boolean)
 Dim nLineCount As Long, nScrollDir As Long
 nLineCount = Delta \ WHEEL_DELTA
 If nLineCount >  0  Then
    nScrollDir = SB_LINELEFT 'SB_LINEUP
 Else
    nScrollDir = SB_LINERIGHT 'SB_LINEDOWN
    nLineCount = -nLineCount
 End If
 Do
    PostMessage m_Form.hWnd, WM_HSCROLL, nScrollDir, ByVal  0 &
    'PostMessage m_Form.hWnd, WM_VSCROLL, nScrollDir, ByVal 0&
    nLineCount = nLineCount -  1 
 Loop While nLineCount
 
 Cancel = True 'Предотвращаем дальнейшую обработку WM_MOUSEWHEEL
End Sub

Версия примера с поддержкой Access 2010: 10808021 .
...
Рейтинг: 0 / 0
25 сообщений из 39, страница 1 из 2
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Использование функций WinAPI в Access
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]