原文地址 一、区划代码编制规则 (一)为统一、规范地编制县以下行政区划代码,满足建立统计上使用的全国行政区划代码库的需要,特制定本规则。 (二)行政区划编码应做到不重、不漏,留有备用号。 (三)县以下行政区
分类: 杂谈
2019,诸事皆宜,助君发财
2019年到了,QDAC 项目也进入七年之痒,未来一年 QDAC 项目的重点将在 QSocket 和FMX 的组件的研发(毕竟 VCL 框架已经比较成熟,各个组件比较完备),其它完成的模块以维护为主,暂时不进行大规模的变动和性能优化。对于 QScript 部分估计 2019 年仍不会实质性切入,以技术预研为主,毕竟与其
推荐一款免费ssh工具 FinalShell完全替代XShell
FinalShell是一体化的的服务器,网络管理软件,不仅是ssh客户端,还是功能强大的开发,运维工具,充分满足开发,运维需求. 特色功能: 免费海外服务器远程桌面加速,ssh加速,双边tcp加速,内网穿透. Windows版下载地址: http://www.hostbuf.com/downloads/finalshe
[译] RAD Studio 2018 年激动人心的开发进程(简译)
原文链接 关于 10.2.3 : 增强 VCL 对高 DPI 支持 提升 FMX 框架品质 提高 C++ Builder 功能,加入 CMake 命令行和 C++ 命名重构支持。CMake 提供对 Ninja 并行编译框架支持。 为 RAD Server 提供 Ext JS 支持 10.2.3 可能需要卸载重装,但
[杂谈]Rad Studio 2018年2月份热修复的变动说明(含 2004 修正)
下述文件对比含 2004 版修正,加粗的为本次热修复变动的文件 1、Winapi.WinSock2 * inet_pton 函数改为延迟加载。这个函数是 Vista 开始支持的,如果不延迟加载(实际上相当于在 XP 上就不会加载),在 XP 上无法导入这个函数,程序就会出错。 2、System.Sysutils.pas
[FMX] FMX 动画类的一个辅助增强
本增强的目的是解决动画对象只支持 published 的有效的几种属性的问题,确切的说,这是一个适配器,通过匿名函数建立与非 published 属性的适配。我在 [FMX] Delphi 中 TAnimation 设计的几点值得商榷的地方 一文中讨论了 FMX 动画支持类的一些值得商榷的地方和改动,而这个增强从另一个
[杂谈]系统对话框(如浏览目录)被隐藏到主窗体后面造成程序无法操作的临时处理方式
说实在话,我被这个问题困扰不知道多少年了,具体的原因我实际上到现在为止仍未找到。不过这里提供一个临时的解决办法,使用定时器来检查当前进程的活动窗口与 Screen.ActiveForm 是否一致,如果不一致,则检查 Screen.ActiveForm 是否被禁用了(注意不要看它的 Enabled,而是调用 API),如
[杂谈] 一个关于 as 的小测试
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
procedure TForm1.Button1Click(Sender: TObject); var B:TButton; I: Integer; ATime:Cardinal; begin ATime:=GetTickCount; for I := 0 to 99999999 do B:=Sender as TButton; ATime:=GetTickCount-ATime; Memo1.Lines.Add('as time:'+IntToStr(ATime)+'ms'); ATime:=GetTickCount; for I := 0 to 99999999 do B:=TButton(Sender); ATime:=GetTickCount-ATime; Memo1.Lines.Add('direct time:'+IntToStr(ATime)+'ms'); end; |
好吧,我们已经知道 ASender 肯定是一个 TButton 类型的对象,然后循环了 1 亿次,以便放大问题。我们看下输出结果: as time:578ms direct time:219ms 也就是说,用 as 转换花费的时间,要比直接强
[工具]ScreenRuler,使用显示器来测量长度
运行效果: 下载:screenruler 使用说明:这么简单的软件,不需要啥说明了吧。
[杂谈]中秋月圆人团圆,国庆国安家平安
祝大家中秋国庆双节快乐,万事如意,事事顺心。祝假日还在码码的码农们节日码码无Bug,工资倍倍翻!
[FMX]FMX 编写 Windows 平台下 DLL 需要解决的两个问题小结
1、在 FMX.Platform.Win 中,平台退出时,没有正确释放 FApplicationHWND 窗口,这样子造成模块释放后,窗口依然存在,所以这个需要修改 FMX.Platform.Win 的代码,以修正这一问题; 2、在 FMX.Forms.Win 中, 平台退出时,没有正确释放 FTimerActionH
[FMX]使用 FMX 实现的左侧菜单效果
这个只是让你看看,并没有代码提供。使用 FMX + QPlugins 实现,菜单实际上是由不同的服务注册提供的。 现在常规的菜单都喜欢放在上边,实际上对现代宽屏的空间利用来说是一个浪费,而浪费是可耻的,所以希望大家多多使用类似这种左侧菜单的设计,把更多的空间留给真正有用的内容使用。 现在的效果只是一个设计上的预览,将来
[杂谈]Delphi 与 VC 通过接口交互时的一点问题的说明
首先,调用都是使用 stdcall,但是在返回接口类型时,VC 和 Delphi 对调用的处理不一致,造成接口无法正常使用。 通过查看返回接口和普通类型的值的对比,可以发现 Delphi 在实现返回接口的调用时,对对象的地址使用了esp+8,而对普通类型时,对象的地址取的是esp+4,这样就造成两者对应的对象原始地址错
[春茶上市]2017年自家产春茶上市,数量有限,售完即止
【种类】 绿茶,炒青,雨前茶 【炒制日期】 2017年4月13日至4月18日(因人工和产量原因,不能一次性炒制) 【购买链接】 淘宝(注:因个人家茶叶自行炒制,故无食品许可证,无法直接上架淘宝,介意勿拍,960元/斤)
官方THTTPClient.Post方法【低级、严重】bug — 需留意
我一直都在寻找各种业务功能的最简单写法,用减法的模式来开发软件。如果有比我的写法更简单的方法,请留言告知。 事情经过: 今日下午用THTTPClient.Post方法 提交的时候,服务端老是自动过滤掉,百思不得其解。花费近2小时调试 检查了很多遍程序 依然不行。于是就开始怀疑 THttpClient的问题,我切换成in
[Bug]官方HttpClient的一处Bug及解决办法
Delphi/C++ Builder 新增加的 TNetHttpClient/THttpClient 在通讯时,对 304 的错误处理不正确,304 在 HTTP 协议的标准是未变更,但在 System.Net.HttpClient.Android/Windows/Mac 里,都错误的当成了重定向处理。在官方的修订出来
[杂谈]Delphi/C++ Builder 10.2 技术预览视频
纯真IP数据库解析Delphi D10.1下正常使用
直接一个单元,代码分享出来。
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 |
unit Net.IPLocation; interface uses System.Classes, System.SysUtils, Winapi.WinSock, Vcl.Forms, System.Math, System.SyncObjs; type TIPLocation = class(TObject) private QQWryFileName: string; QQWryFileStream: TBufferedFileStream; QQWryFileSize: Cardinal; IPRecordNum: Cardinal; FirstIPIndexOffset, LastIPIndexOffset: Cardinal; FLock: TCriticalSection; function GetQQWryFileName: string; function GetQQWryFileSize: Cardinal; function GetIPRecordNum: Cardinal; function GetQQWryDate: TDate; function GetQQWryDataFrom: string; function GetIPLocation(IPLocationOffset: Cardinal): TStringlist; function GetIPMsg(IPRecordID: Cardinal): TStringlist; function GetIPRecordID(IP: string): Cardinal; function GetIPValue(IP: string): Cardinal; public constructor Create(cQQWryFileName: string); destructor Destroy; override; function GetLocation(IP: string): String; end; function IPLocation: TIPLocation; implementation var __IPLocation: TIPLocation; function IPLocation: TIPLocation; begin if __IPLocation = nil then __IPLocation := TIPLocation.Create(ExtractFilePath(ParamStr(0)) + 'qqwry.dat'); Result := __IPLocation; end; { TIPLocation } constructor TIPLocation.Create(cQQWryFileName: string); begin inherited Create; FLock := TCriticalSection.Create; QQWryFileName := cQQWryFileName; QQWryFileStream := TBufferedFileStream.Create(QQWryFileName, fmOpenRead or fmShareDenyWrite, 0); QQWryFileSize := QQWryFileStream.Size; QQWryFileStream.Read(FirstIPIndexOffset, 4); QQWryFileStream.Read(LastIPIndexOffset, 4); IPRecordNum := (LastIPIndexOffset - FirstIPIndexOffset) div 7 + 1; end; destructor TIPLocation.Destroy; begin QQWryFileStream.Free; FLock.Free; inherited Destroy; end; function TIPLocation.GetIPLocation(IPLocationOffset: Cardinal): TStringlist; const // 实际信息字串存放位置的重定向模式 REDIRECT_MODE_1 = 1; REDIRECT_MODE_2 = 2; var RedirectMode: byte; CountryFirstOffset, CountrySecondOffset: Cardinal; CountryMsg, AreaMsg: string; // function ReadString(StringOffset: Cardinal): ansistring; var ReadByte: ansichar; begin Result := ''; QQWryFileStream.Seek(StringOffset, soFromBeginning); QQWryFileStream.Read(ReadByte, 1); while ord(ReadByte) <> 0 do begin Result := Result + ReadByte; QQWryFileStream.Read(ReadByte, 1); end; end; // function ReadArea(AreaOffset: Cardinal): ansistring; var ModeByte: byte; ReadAreaOffset: Cardinal; begin ReadAreaOffset := 0; QQWryFileStream.Seek(AreaOffset, soFromBeginning); QQWryFileStream.Read(ModeByte, 1); if (ModeByte = REDIRECT_MODE_1) or (ModeByte = REDIRECT_MODE_2) then begin QQWryFileStream.Read(ReadAreaOffset, 3); if ReadAreaOffset = 0 then Result := '未知地区' else Result := ReadString(ReadAreaOffset); end else begin Result := ReadString(AreaOffset); end; end; begin CountryFirstOffset := 0; CountrySecondOffset := 0; // 跳过4个字节,该4字节内容为该条IP信息里IP地址段中的终止IP值 QQWryFileStream.Seek(IPLocationOffset + 4, soFromBeginning); // 读取国家信息的重定向模式值 QQWryFileStream.Read(RedirectMode, 1); // 重定向模式1的处理 if RedirectMode = REDIRECT_MODE_1 then begin // 模式值为1,则后3个字节的内容为国家信息的重定向偏移值 QQWryFileStream.ReadData(CountryFirstOffset, 3); // 进行重定向 QQWryFileStream.Seek(CountryFirstOffset, soFromBeginning); // 第二次读取国家信息的重定向模式 QQWryFileStream.Read(RedirectMode, 1); // 第二次重定向模式为模式2的处理 if RedirectMode = REDIRECT_MODE_2 then begin // 后3字节的内容即为第二次重定向偏移值 QQWryFileStream.ReadData(CountrySecondOffset, 3); // 读取第二次重定向偏移值下的字符串值,即为国家信息 CountryMsg := ReadString(CountrySecondOffset); // 若第一次重定向模式为1,进行重定向后读取的第二次重定向模式为2, // 则地区信息存放在第一次国家信息偏移值的后面 QQWryFileStream.Seek(CountryFirstOffset + 4, soFromBeginning); // 第二次重定向模式不是模式2的处理 end else begin CountryMsg := ReadString(CountryFirstOffset); end; // 在重定向模式1下读地区信息值 AreaMsg := ReadArea(QQWryFileStream.Position); // 重定向模式2的处理 end else if RedirectMode = REDIRECT_MODE_2 then begin QQWryFileStream.ReadData(CountrySecondOffset, 3); CountryMsg := ReadString(CountrySecondOffset); AreaMsg := ReadArea(IPLocationOffset + 8); // 不是重定向模式的处理,存放的即是IP地址信息 end else begin CountryMsg := ReadString(QQWryFileStream.Position - 1); AreaMsg := ReadArea(QQWryFileStream.Position); end; Result := TStringlist.Create; Result.Add(CountryMsg); Result.Add(AreaMsg); end; function TIPLocation.GetIPMsg(IPRecordID: Cardinal): TStringlist; var aryStartIP: array [1 .. 4] of byte; strStartIP: string; EndIPOffset: Cardinal; aryEndIP: array [1 .. 4] of byte; strEndIP: string; i: integer; begin EndIPOffset := 0; // 根据记录ID号移到该记录号的索引处 QQWryFileStream.Seek(FirstIPIndexOffset + (IPRecordID - 1) * 7, soFromBeginning); // 索引的前4个字节为起始IP地址 QQWryFileStream.Read(aryStartIP, 4); // 后3个字节是内容区域的偏移值 // QQWryFileStream.Read(EndIPOffset, 3); QQWryFileStream.ReadData(EndIPOffset, 3); // 移至内容区域 QQWryFileStream.Seek(EndIPOffset, soFromBeginning); // 内容区域的前4个字节为终止IP地址 QQWryFileStream.Read(aryEndIP, 4); // 将起止IP地址转换为点分的形式 strStartIP := ''; for i := 4 downto 1 do begin if i <> 1 then strStartIP := strStartIP + IntToStr(aryStartIP[i]) + '.' else strStartIP := strStartIP + IntToStr(aryStartIP[i]); end; strEndIP := ''; for i := 4 downto 1 do begin if i <> 1 then strEndIP := strEndIP + IntToStr(aryEndIP[i]) + '.' else strEndIP := strEndIP + IntToStr(aryEndIP[i]); end; Result := TStringlist.Create; Result.Add(strStartIP); Result.Add(strEndIP); // 获取该条记录下的IP地址信息 // 以下三者是统一的:①内容区域的偏移值 ②终止IP地址的存放位置 ③国家信息紧接在终止IP地址存放位置后 Result.AddStrings(GetIPLocation(EndIPOffset)); end; function TIPLocation.GetIPRecordID(IP: string): Cardinal; function SearchIPRecordID(IPRecordFrom, IPRecordTo, IPValue: Cardinal) : Cardinal; var CompareIPValue1, CompareIPValue2: Cardinal; begin Result := 0; CompareIPValue1 := 0; CompareIPValue2 := 0; QQWryFileStream.Seek(FirstIPIndexOffset + ((IPRecordTo - IPRecordFrom) div 2 + IPRecordFrom - 1) * 7, soFromBeginning); QQWryFileStream.Read(CompareIPValue1, 4); QQWryFileStream.Seek(FirstIPIndexOffset + ((IPRecordTo - IPRecordFrom) div 2 + IPRecordFrom) * 7, soFromBeginning); QQWryFileStream.Read(CompareIPValue2, 4); // 找到了 if (IPValue >= CompareIPValue1) and (IPValue < CompareIPValue2) then begin Result := (IPRecordTo - IPRecordFrom) div 2 + IPRecordFrom; end else // 后半段找 if IPValue > CompareIPValue1 then begin Result := SearchIPRecordID((IPRecordTo - IPRecordFrom) div 2 + IPRecordFrom + 1, IPRecordTo, IPValue); end else // 前半段找 if IPValue < CompareIPValue1 then begin Result := SearchIPRecordID(IPRecordFrom, (IPRecordTo - IPRecordFrom) div 2 + IPRecordFrom - 1, IPValue); end; end; begin Result := SearchIPRecordID(1, GetIPRecordNum, GetIPValue(IP)); end; function TIPLocation.GetIPRecordNum: Cardinal; begin Result := IPRecordNum; end; function TIPLocation.GetIPValue(IP: string): Cardinal; var tsIP: TStringlist; i: integer; function SplitStringToStringlist(aString: string; aSplitChar: string) : TStringlist; begin Result := TStringlist.Create; while pos(aSplitChar, aString) > 0 do begin Result.Add(copy(aString, 1, pos(aSplitChar, aString) - 1)); aString := copy(aString, pos(aSplitChar, aString) + 1, length(aString) - pos(aSplitChar, aString)); end; Result.Add(aString); end; begin tsIP := SplitStringToStringlist(IP, '.'); Result := 0; for i := 3 downto 0 do begin Result := Result + StrToInt(tsIP[i]) * trunc(power(256, 3 - i)); end; end; function TIPLocation.GetLocation(IP: string): String; begin FLock.Enter; try Result := GetIPMsg(GetIPRecordID(IP))[2]; finally FLock.Leave; end; end; function TIPLocation.GetQQWryDataFrom: string; begin Result := GetIPMsg(GetIPRecordNum)[2]; end; function TIPLocation.GetQQWryDate: TDate; var DateString: string; begin DateString := GetIPMsg(GetIPRecordNum)[3]; DateString := copy(DateString, 1, pos('IP数据', DateString) - 1); DateString := StringReplace(DateString, '年', '-', [rfReplaceAll, rfIgnoreCase]); DateString := StringReplace(DateString, '月', '-', [rfReplaceAll, rfIgnoreCase]); DateString := StringReplace(DateString, '日', '-', [rfReplaceAll, rfIgnoreCase]); Result := StrToDate(DateString); end; function TIPLocation.GetQQWryFileName: string; begin Result := QQWryFileName; end; function TIPLocation.GetQQWryFileSize: Cardinal; begin Result := QQWryFileSize; end; initialization finalization if __IPLocation <> nil then __IPLocation.Free; end. |
[FMX] Delphi 中 TAnimation 设计的几点值得商榷的地方
在 FMX 中,动画是很好用的一个东西,但是 FMX 动画的基类 TAnimation 的设计,在我看来有一点值得商榷,我们来看 Start 函数的实现:
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 |
procedure TAnimation.Start; var Control: IControl; SaveDuration: Single; begin if not FLoop then FTickCount := 0; if Supports(Parent, IControl, Control) and (not Control.Visible) then Exit; if AutoReverse then begin if Running then FInverse := FSavedInverse else FSavedInverse := FInverse; end; if (Abs(FDuration) < 0.001) or (Root = nil) or (csDesigning in ComponentState) then begin { immediate animation } SaveDuration := FDuration; try FDelayTime := 0; FDuration := 1; if FInverse then FTime := 0 else FTime := FDuration; FRunning := True; ProcessAnimation; DoProcess; FRunning := False; FTime := 0; DoFinish; finally FDuration := SaveDuration; end; end else begin FDelayTime := FDelay; FRunning := True; if FInverse then FTime := FDuration else FTime := 0; if FDelay = 0 then begin FirstFrame; ProcessAnimation; DoProcess; end; if AniThread = nil then FAniThread := TAniThread.Create; TAniThread(AniThread).AddAnimation(Self); if not AniThread.Enabled then Stop else FEnabled := True; end; end; |
注意两个地方: 第一个地方:
1 2 |
if Supports(Parent, IControl, Control) and (not Control.Visible) then Exit; |
个
学习中的一些牢骚。栈/堆地址标准写法。
我一直都在寻找各种业务功能的最简单写法,用减法的模式来开发软件。下面是我的写法,如果有更简单的方法,请留言告知。 本人再学习的过程中,遇到很多难题,delphi很多地方自身的设计就很乱。 比如对参数修饰符的理解,网上100篇文章 90篇都有问题 错误率非常高。delphi 的数据类型有很多 同一个参数修饰符 修饰 不同